Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
balugaq committed Nov 10, 2024
1 parent e4594e2 commit c478a1c
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 15 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.ytdd9527.networksexpansion</groupId>
<artifactId>NetworksExpansion</artifactId>
<version>2.1-Alpha-5</version>
<version>2.1-Alpha-6</version>

<distributionManagement>
<repository>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.ytdd9527.networksexpansion.utils;

import io.github.thebusybiscuit.slimefun4.libraries.dough.collections.Pair;
import lombok.experimental.UtilityClass;

import java.lang.reflect.Field;
Expand Down Expand Up @@ -68,4 +69,19 @@ public static <T, V> T getProperty(Object o, Class<V> clazz, String fieldName) t

return null;
}

public static Pair<Field, Class<?>> getDeclaredFieldsRecursively(Class<?> clazz, String fieldName){
try{
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return new Pair<>(field, clazz);
}catch (Throwable e){
clazz = clazz.getSuperclass();
if(clazz == null){
return null;
} else {
return getDeclaredFieldsRecursively(clazz, fieldName);
}
}
}
}
56 changes: 56 additions & 0 deletions src/main/java/com/ytdd9527/networksexpansion/utils/WorldUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.ytdd9527.networksexpansion.utils;

import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;

import java.lang.reflect.Field;

public class WorldUtils {
protected static Class<?> CraftBlockStateClass;
protected static Field IBlockDataField;
protected static Field BlockPositionField;
protected static Field WorldField;
protected static Field WeakWorldField;
protected static boolean invokeBlockStateSuccess = false;
static {
try {
World sampleWorld= Bukkit.getWorlds().get(0);
BlockState blockstate=sampleWorld.getBlockAt(0, 0, 0).getState();
var result= ReflectionUtil.getDeclaredFieldsRecursively(blockstate.getClass(),"data");
IBlockDataField = result.getFirstValue();
IBlockDataField.setAccessible(true);
CraftBlockStateClass = result.getSecondValue();
BlockPositionField = ReflectionUtil.getDeclaredFieldsRecursively(CraftBlockStateClass,"position").getFirstValue();
BlockPositionField.setAccessible(true);
WorldField = ReflectionUtil.getDeclaredFieldsRecursively(CraftBlockStateClass,"world").getFirstValue();
WorldField.setAccessible(true);
WeakWorldField = ReflectionUtil.getDeclaredFieldsRecursively(CraftBlockStateClass,"weakWorld").getFirstValue();
WeakWorldField.setAccessible(true);
invokeBlockStateSuccess = true;
} catch (Throwable ignored) {

}
}
public static boolean copyBlockState(BlockState stateToSet, Block toBlock){
if (!invokeBlockStateSuccess) {
return false;
}

BlockState originalState = toBlock.getState();
if (!CraftBlockStateClass.isInstance(originalState) ||!CraftBlockStateClass.isInstance(stateToSet)) {
return false;
}

try {
BlockPositionField.set(stateToSet, BlockPositionField.get(originalState));
WorldField.set(stateToSet, WorldField.get(originalState));
WeakWorldField.set(stateToSet, WeakWorldField.get(originalState));
stateToSet.update(true, false);
return true;
} catch (Throwable ignored) {
return false;
}
}
}
137 changes: 123 additions & 14 deletions src/main/java/io/github/sefiraat/networks/commands/NetworksMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.xzavier0722.mc.plugin.slimefun4.storage.util.StorageCacheUtils;
import com.ytdd9527.networksexpansion.core.items.unusable.AbstractBlueprint;
import com.ytdd9527.networksexpansion.implementation.machines.unit.NetworksDrawer;
import com.ytdd9527.networksexpansion.utils.WorldUtils;
import io.github.bakedlibs.dough.collections.Pair;
import io.github.bakedlibs.dough.skins.PlayerHead;
import io.github.bakedlibs.dough.skins.PlayerSkin;
Expand All @@ -30,12 +31,14 @@
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import org.bukkit.Bukkit;
import org.bukkit.FluidCollisionMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
Expand All @@ -55,33 +58,33 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unused"})
public class NetworksMain implements TabExecutor {
private static final Map<String, Pair<Location, Location>> SELECTED_POS = new HashMap<>();

private static final Map<UUID, Pair<Location, Location>> SELECTED_POS = new HashMap<>();
public static Location getPos1(Player p) {
if (SELECTED_POS.get(p.getName()) == null) {
if (SELECTED_POS.get(p.getUniqueId()) == null) {
return null;
}
return SELECTED_POS.get(p.getName()).getFirstValue();
return SELECTED_POS.get(p.getUniqueId()).getFirstValue();
}

public static Location getPos2(Player p) {
if (SELECTED_POS.get(p.getName()) == null) {
if (SELECTED_POS.get(p.getUniqueId()) == null) {
return null;
}
return SELECTED_POS.get(p.getName()).getSecondValue();
return SELECTED_POS.get(p.getUniqueId()).getSecondValue();
}

public static void setPos1(Player p, Location pos) {
SELECTED_POS.put(p.getName(), new Pair<>(pos, getPos2(p)));
SELECTED_POS.put(p.getUniqueId(), new Pair<>(pos, getPos2(p)));
}

public static void setPos2(Player p, Location pos) {
SELECTED_POS.put(p.getName(), new Pair<>(getPos1(p), pos));
SELECTED_POS.put(p.getUniqueId(), new Pair<>(getPos1(p), pos));
}

public static String locationToString(Location l) {
Expand Down Expand Up @@ -353,6 +356,104 @@ public static void worldeditPos2(Player player, Location location) {
}
}

public static void worldeditClone(Player player) {
worldeditClone(player, false);
}
public static void worldeditClone(Player player, boolean overrideData) {
if (getPos1(player) == null || getPos2(player) == null) {
player.sendMessage(Networks.getLocalizationService().getString("messages.commands.worldedit.must-select-area"));
return;
}

if (!Objects.equals(getPos1(player).getWorld().getUID(), getPos2(player).getWorld().getUID())) {
player.sendMessage(Networks.getLocalizationService().getString("messages.commands.worldedit.must-select-same-world"));
return;
}

player.sendMessage(String.format(Networks.getLocalizationService().getString("messages.commands.worldedit.pasting-block"), locationToString(getPos1(player)), locationToString(getPos2(player))));
final long currentMillSeconds = System.currentTimeMillis();

final AtomicInteger count = new AtomicInteger();
final Location playerLocation = player.getLocation();
final ItemStack itemInHand = player.getItemInHand();

final Location pos1 = getPos1(player);
final int dx = playerLocation.getBlockX() - pos1.getBlockX();
final int dy = playerLocation.getBlockY() - pos1.getBlockY();
final int dz = playerLocation.getBlockZ() - pos1.getBlockZ();

Bukkit.getScheduler().runTask(Networks.getInstance(), () -> {
doWorldEdit(getPos1(player), getPos2(player), (fromLocation -> {
final Block fromBlock = fromLocation.getBlock();
final Block toBlock = playerLocation.getWorld().getBlockAt(fromLocation.getBlockX() + dx, fromLocation.getBlockY() + dy, fromLocation.getBlockZ() + dz);
final SlimefunItem slimefunItem = StorageCacheUtils.getSfItem(fromLocation);
final Location toLocation = toBlock.getLocation();

// Block Data
WorldUtils.copyBlockState(fromBlock.getState(), toBlock);

// Count means successful pasting block data. Not including Slimefun data.
count.addAndGet(1);

// Slimefun Data
if (slimefunItem == null) {
return;
}

// Call Handler
slimefunItem.callItemHandler(BlockPlaceHandler.class, handler -> handler.onPlayerPlace(
new BlockPlaceEvent(
toBlock,
toBlock.getState(),
toBlock.getRelative(BlockFace.SOUTH),
itemInHand,
player,
true
)
));

SlimefunBlockData fromSlimefunBlockData = Slimefun.getDatabaseManager().getBlockDataController().getBlockData(fromLocation);
if (overrideData) {
Slimefun.getDatabaseManager().getBlockDataController().removeBlock(toLocation);
}

if (StorageCacheUtils.hasBlock(toLocation)) {
return;
}

// Slimefun Block
Slimefun.getDatabaseManager().getBlockDataController().createBlock(toLocation, slimefunItem.getId());
SlimefunBlockData toSlimefunBlockData = Slimefun.getDatabaseManager().getBlockDataController().getBlockData(toLocation);

// SlimefunBlockData
if (fromSlimefunBlockData == null || toSlimefunBlockData == null) {
return;
}

Map<String, String> data = fromSlimefunBlockData.getAllData();
for (String key : data.keySet()) {
toSlimefunBlockData.setData(key, data.get(key));
}

// BlockMenu
final BlockMenu fromMenu = fromSlimefunBlockData.getBlockMenu();
final BlockMenu toMenu = toSlimefunBlockData.getBlockMenu();

if (fromMenu == null || toMenu == null) {
return;
}

ItemStack[] contents = fromMenu.getContents();
for (int i = 0; i < contents.length; i++) {
if (contents[i] != null) {
toMenu.getInventory().setItem(i, contents[i].clone());
}
}
}));
player.sendMessage(String.format(Networks.getLocalizationService().getString("messages.commands.worldedit.paste-done"), count, System.currentTimeMillis() - currentMillSeconds));
});
}

public static void worldeditPaste(Player player, String sfid) {
worldeditPaste(player, sfid, false, false);
}
Expand Down Expand Up @@ -415,9 +516,9 @@ public static void worldeditPaste(Player player, String sfid, boolean overrideDa
}
skin = skin0;
isHead = isHead0;
// java's operation ↑

doWorldEdit(getPos1(player), getPos2(player), (location -> {
final Block targetBlock = getPos1(player).getWorld().getBlockAt(location);
final Block targetBlock = location.getBlock();
sfItem.callItemHandler(BlockPlaceHandler.class, h -> h.onPlayerPlace(
new BlockPlaceEvent(
targetBlock,
Expand Down Expand Up @@ -923,6 +1024,14 @@ public boolean onCommand(@Nonnull CommandSender sender, @Nonnull Command command
}
}

case "clone" -> {
if (args.length <= 2) {
worldeditClone(player);
} else if (args.length <= 3) {
worldeditClone(player, "override".equalsIgnoreCase(args[2]));
}
}

case "paste" -> {
if (args.length <= 2) {
player.sendMessage(getErrorMessage(ErrorType.MISSING_REQUIRED_ARGUMENT, "sfId"));
Expand All @@ -932,13 +1041,13 @@ public boolean onCommand(@Nonnull CommandSender sender, @Nonnull Command command
boolean force = false;
switch (args.length) {
case 5 -> {
if (args[3].toLowerCase(Locale.ROOT).equals("override")) {
if ("override".equalsIgnoreCase(args[3])) {
overrideData = true;
}
force = Boolean.parseBoolean(args[4]);
}
case 4 -> {
if (args[3].toLowerCase(Locale.ROOT).equals("override")) {
if ("override".equalsIgnoreCase(args[3])) {
overrideData = true;
}
}
Expand Down Expand Up @@ -1166,7 +1275,7 @@ public void fixBlueprint(Player player, String before) {
case "fillquantum", "addstorageitem", "reducestorageitem", "setquantum" -> List.of("<amount>");
case "fixblueprint" -> List.of("<keyInMeta>");
case "setcontainerid" -> List.of("<containerId>");
case "worldedit" -> List.of("pos1", "pos2", "paste", "clear", "blockmenu", "blockinfo");
case "worldedit" -> List.of("pos1", "pos2", "paste", "clear", "clone", "blockmenu", "blockinfo");
default -> List.of();
};
}
Expand Down

0 comments on commit c478a1c

Please sign in to comment.