mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-22 16:39:28 +00:00
@@ -18,6 +18,7 @@ dependencies {
|
||||
implementation(project(":core"))
|
||||
implementation(project(":bukkit"))
|
||||
implementation(project(":bukkit:legacy"))
|
||||
implementation(project(":bukkit:compatibility"))
|
||||
|
||||
implementation("net.kyori:adventure-platform-bukkit:${rootProject.properties["adventure_platform_version"]}")
|
||||
implementation("com.saicone.rtag:rtag-item:${rootProject.properties["rtag_version"]}")
|
||||
|
||||
@@ -92,8 +92,6 @@ resource-pack:
|
||||
suffix: "minecraft/items"
|
||||
- type: parent_path_suffix
|
||||
suffix: "minecraft/models/item"
|
||||
- type: parent_path_suffix
|
||||
suffix: "minecraft/atlases"
|
||||
resolution:
|
||||
type: merge_json
|
||||
deeply: true
|
||||
@@ -117,6 +115,11 @@ resource-pack:
|
||||
resolution:
|
||||
type: merge_json
|
||||
deeply: false
|
||||
- term:
|
||||
type: parent_path_suffix
|
||||
suffix: "minecraft/atlases"
|
||||
resolution:
|
||||
type: merge_atlas
|
||||
|
||||
item:
|
||||
# Add a <!i> tag on item name and lore
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
items:
|
||||
default:chinese_lantern:
|
||||
material: paper
|
||||
custom-model-data: 3001
|
||||
custom-model-data: 3000
|
||||
data:
|
||||
item-name: "<!i><i18n:item.chinese_lantern>"
|
||||
model:
|
||||
|
||||
@@ -56,4 +56,5 @@ categories:
|
||||
icon: default:chinese_lantern
|
||||
list:
|
||||
- default:chinese_lantern
|
||||
- default:fairy_flower
|
||||
- default:fairy_flower
|
||||
- default:reed
|
||||
@@ -2,6 +2,7 @@ i18n:
|
||||
en:
|
||||
item.chinese_lantern: "Chinese Lantern"
|
||||
item.fairy_flower: "Fairy Flower"
|
||||
item.reed: "Reed"
|
||||
item.bench: "Bench"
|
||||
item.table_lamp: "Table Lamp"
|
||||
item.wooden_chair: "Wooden Chair"
|
||||
@@ -36,6 +37,7 @@ i18n:
|
||||
zh_cn:
|
||||
item.chinese_lantern: "灯笼"
|
||||
item.fairy_flower: "仙灵花"
|
||||
item.reed: "芦苇"
|
||||
item.bench: "长椅"
|
||||
item.table_lamp: "台灯"
|
||||
item.wooden_chair: "木椅"
|
||||
|
||||
@@ -235,7 +235,7 @@ items:
|
||||
# To prevent errors, we use tree feature from vanilla here
|
||||
feature: minecraft:fancy_oak
|
||||
bone-meal-success-chance: 0.45
|
||||
tags:
|
||||
bottom-block-tags:
|
||||
- minecraft:dirt
|
||||
- minecraft:farmland
|
||||
- minecraft:sand
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
items:
|
||||
default:fairy_flower:
|
||||
material: paper
|
||||
custom-model-data: 3000
|
||||
custom-model-data: 3001
|
||||
data:
|
||||
item-name: "<!i><i18n:item.fairy_flower>"
|
||||
model:
|
||||
@@ -11,6 +11,18 @@ items:
|
||||
behavior:
|
||||
type: block_item
|
||||
block: default:fairy_flower
|
||||
default:reed:
|
||||
material: paper
|
||||
custom-model-data: 3002
|
||||
data:
|
||||
item-name: "<!i><i18n:item.reed>"
|
||||
model:
|
||||
template: default:model/simplified_generated
|
||||
arguments:
|
||||
path: "minecraft:item/custom/reed"
|
||||
behavior:
|
||||
type: liquid_collision_block_item
|
||||
block: default:reed
|
||||
blocks:
|
||||
default:fairy_flower:
|
||||
settings:
|
||||
@@ -19,6 +31,7 @@ blocks:
|
||||
- default:sound/grass
|
||||
overrides:
|
||||
item: default:fairy_flower
|
||||
push-reaction: DESTROY
|
||||
behavior:
|
||||
type: bush_block
|
||||
loot:
|
||||
@@ -27,7 +40,7 @@ blocks:
|
||||
item: default:fairy_flower
|
||||
state:
|
||||
id: 0
|
||||
state: tripwire:0
|
||||
state: sugar_cane:0
|
||||
models:
|
||||
- path: "minecraft:block/custom/fairy_flower_1"
|
||||
weight: 100
|
||||
@@ -48,4 +61,24 @@ blocks:
|
||||
generation:
|
||||
parent: "minecraft:block/custom/fairy_flower_1"
|
||||
textures:
|
||||
"0": "minecraft:block/custom/fairy_flower_4"
|
||||
"0": "minecraft:block/custom/fairy_flower_4"
|
||||
default:reed:
|
||||
settings:
|
||||
template:
|
||||
- default:hardness/none
|
||||
- default:sound/grass
|
||||
overrides:
|
||||
item: default:reed
|
||||
push-reaction: DESTROY
|
||||
behavior:
|
||||
type: on_liquid_block
|
||||
liquid-type: water
|
||||
loot:
|
||||
template: "default:loot_table/basic"
|
||||
arguments:
|
||||
item: default:reed
|
||||
state:
|
||||
id: 1
|
||||
state: sugar_cane:1
|
||||
model:
|
||||
path: "minecraft:block/custom/reed"
|
||||
@@ -34,6 +34,7 @@
|
||||
"from": [7, 28, 7],
|
||||
"to": [9, 30, 9],
|
||||
"rotation": {"angle": 0, "axis": "y", "origin": [7, 28, 7]},
|
||||
"shade": false,
|
||||
"faces": {
|
||||
"north": {"uv": [15, 0, 16, 1], "texture": "#0"},
|
||||
"east": {"uv": [15, 0, 16, 1], "texture": "#0"},
|
||||
@@ -43,15 +44,5 @@
|
||||
"down": {"uv": [15, 0, 16, 1], "texture": "#0"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"display": {
|
||||
"head": {
|
||||
"translation": [0, 18.5, 0]
|
||||
},
|
||||
"fixed": {
|
||||
"rotation": [-90, 0, 0],
|
||||
"translation": [0, 0, -15],
|
||||
"scale": [2, 2, 2]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"ambientocclusion": false,
|
||||
"textures": {
|
||||
"0": "block/custom/reed",
|
||||
"particle": "block/custom/reed"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [-0.5, -3, 0.25],
|
||||
"to": [19.5, 29, 0.25],
|
||||
"shade": false,
|
||||
"rotation": {"angle": -45, "axis": "y", "origin": [-0.5, -3, 2.25]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 10, 16], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 0, 16], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 10, 16], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 0, 16], "texture": "#0"},
|
||||
"up": {"uv": [0, 0, 0, 10], "rotation": 270, "texture": "#0"},
|
||||
"down": {"uv": [0, 0, 0, 10], "rotation": 90, "texture": "#0"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [2, -3, 14.75],
|
||||
"to": [22, 29, 14.75],
|
||||
"shade": false,
|
||||
"rotation": {"angle": 45, "axis": "y", "origin": [2, -3, 16.75]},
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 10, 16], "texture": "#0"},
|
||||
"east": {"uv": [0, 0, 0, 16], "texture": "#0"},
|
||||
"south": {"uv": [0, 0, 10, 16], "texture": "#0"},
|
||||
"west": {"uv": [0, 0, 0, 16], "texture": "#0"},
|
||||
"up": {"uv": [0, 0, 0, 10], "rotation": 270, "texture": "#0"},
|
||||
"down": {"uv": [0, 0, 0, 10], "rotation": 90, "texture": "#0"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"texture_size": [64, 64],
|
||||
"textures": {
|
||||
"0": "item/custom/bench",
|
||||
"particle": "item/custom/bench"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"texture_size": [32, 32],
|
||||
"textures": {
|
||||
"0": "item/custom/table_lamp",
|
||||
"particle": "item/custom/table_lamp"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"texture_size": [32, 32],
|
||||
"textures": {
|
||||
"0": "item/custom/wooden_chair",
|
||||
"particle": "item/custom/wooden_chair"
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 695 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
@@ -15,6 +15,7 @@ repositories {
|
||||
dependencies {
|
||||
compileOnly(project(":core"))
|
||||
compileOnly(project(":shared"))
|
||||
compileOnly(project(":bukkit:compatibility"))
|
||||
compileOnly(project(":bukkit:legacy"))
|
||||
// Anti Grief
|
||||
compileOnly("com.github.Xiao-MoMi:AntiGriefLib:${rootProject.properties["anti_grief_version"]}")
|
||||
|
||||
28
bukkit/compatibility/build.gradle.kts
Normal file
28
bukkit/compatibility/build.gradle.kts
Normal file
@@ -0,0 +1,28 @@
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven("https://repo.papermc.io/repository/maven-public/")
|
||||
maven("https://r.irepo.space/maven/")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":core"))
|
||||
// Platform
|
||||
compileOnly("dev.folia:folia-api:${rootProject.properties["paper_version"]}-R0.1-SNAPSHOT")
|
||||
// NeigeItems
|
||||
compileOnly("pers.neige.neigeitems:NeigeItems:1.21.42")
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
options.encoding = "UTF-8"
|
||||
options.release.set(21)
|
||||
dependsOn(tasks.clean)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package net.momirealms.craftengine.bukkit.compatibility.item;
|
||||
|
||||
import net.momirealms.craftengine.core.item.ExternalItemProvider;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import pers.neige.neigeitems.manager.ItemManager;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class NeigeItemsProvider implements ExternalItemProvider<ItemStack> {
|
||||
|
||||
@Override
|
||||
public String plugin() {
|
||||
return "NeigeItems";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack build(String id, ItemBuildContext context) {
|
||||
return ItemManager.INSTANCE.getItemStack(id, Optional.ofNullable(context.player()).map(it -> (Player) it.platformPlayer()).orElse(null));
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,12 @@ import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.shared.block.EmptyBlockBehavior;
|
||||
|
||||
public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
public static final Key EMPTY = Key.from("craftengine:empty");
|
||||
public static final Key BUSH_BLOCK = Key.from("craftengine:bush_block");
|
||||
public static final Key FALLING_BLOCK = Key.from("craftengine:falling_block");
|
||||
public static final Key LEAVES_BLOCK = Key.from("craftengine:leaves_block");
|
||||
public static final Key STRIPPABLE_BLOCK = Key.from("craftengine:strippable_block");
|
||||
public static final Key SAPLING_BLOCK = Key.from("craftengine:sapling_block");
|
||||
public static final Key ON_LIQUID_BLOCK = Key.from("craftengine:on_liquid_block");
|
||||
|
||||
public static void init() {
|
||||
register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE);
|
||||
@@ -19,5 +19,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors {
|
||||
register(LEAVES_BLOCK, LeavesBlockBehavior.FACTORY);
|
||||
register(STRIPPABLE_BLOCK, StrippableBlockBehavior.FACTORY);
|
||||
register(SAPLING_BLOCK, SaplingBlockBehavior.FACTORY);
|
||||
register(ON_LIQUID_BLOCK, OnLiquidBlockBehavior.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,9 @@ public class BushBlockBehavior extends BlockBehavior {
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
if (arguments.containsKey("tags")) {
|
||||
if (arguments.containsKey("bottom-block-tags")) {
|
||||
return new BushBlockBehavior(MiscUtils.getAsStringList(arguments.get("bottom-block-tags")).stream().map(it -> BlockTags.getOrCreate(Key.of(it))).toList());
|
||||
} else if (arguments.containsKey("tags")) {
|
||||
return new BushBlockBehavior(MiscUtils.getAsStringList(arguments.get("tags")).stream().map(it -> BlockTags.getOrCreate(Key.of(it))).toList());
|
||||
} else {
|
||||
return INSTANCE;
|
||||
@@ -100,7 +102,7 @@ public class BushBlockBehavior extends BlockBehavior {
|
||||
return mayPlaceOn(belowState, world, belowPos);
|
||||
}
|
||||
|
||||
private boolean mayPlaceOn(Object belowState, Object world, Object blockPos) throws ReflectiveOperationException {
|
||||
protected boolean mayPlaceOn(Object belowState, Object world, Object belowPos) throws ReflectiveOperationException {
|
||||
for (Object tag : this.tagsCanSurviveOn) {
|
||||
if ((boolean) Reflections.method$BlockStateBase$hasTag.invoke(belowState, tag)) {
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package net.momirealms.craftengine.bukkit.block.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.block.CustomBlock;
|
||||
import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.shared.block.BlockBehavior;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class OnLiquidBlockBehavior extends BushBlockBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final boolean onWater;
|
||||
private final boolean onLava;
|
||||
|
||||
public OnLiquidBlockBehavior(List<Object> tagsCanSurviveOn, boolean onWater, boolean onLava) {
|
||||
super(tagsCanSurviveOn);
|
||||
this.onWater = onWater;
|
||||
this.onLava = onLava;
|
||||
}
|
||||
|
||||
public boolean onWater() {
|
||||
return this.onWater;
|
||||
}
|
||||
|
||||
public boolean onLava() {
|
||||
return this.onLava;
|
||||
}
|
||||
|
||||
public static class Factory implements BlockBehaviorFactory {
|
||||
@Override
|
||||
public BlockBehavior create(CustomBlock block, Map<String, Object> arguments) {
|
||||
List<String> liquidTypes = MiscUtils.getAsStringList(arguments.getOrDefault("liquid-type", List.of("water")));
|
||||
return new OnLiquidBlockBehavior(List.of(), liquidTypes.contains("water"), liquidTypes.contains("lava"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean mayPlaceOn(Object belowState, Object world, Object belowPos) throws ReflectiveOperationException {
|
||||
Object fluidState = Reflections.method$Level$getFluidState.invoke(world, belowPos);
|
||||
Object fluidStateAbove = Reflections.method$Level$getFluidState.invoke(world, LocationUtils.above(belowPos));
|
||||
if (Reflections.method$FluidState$getType.invoke(fluidStateAbove) != Reflections.instance$Fluids$EMPTY) {
|
||||
return false;
|
||||
}
|
||||
if (this.onWater && (Reflections.method$FluidState$getType.invoke(fluidState) == Reflections.instance$Fluids$WATER || Reflections.field$StateHolder$owner.get(belowState) == Reflections.instance$Blocks$ICE)) {
|
||||
return true;
|
||||
}
|
||||
if (this.onLava && Reflections.method$FluidState$getType.invoke(fluidState) == Reflections.instance$Fluids$LAVA) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package net.momirealms.craftengine.bukkit.entity.furniture;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
||||
import net.momirealms.craftengine.core.entity.furniture.*;
|
||||
@@ -37,11 +35,6 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
|
||||
private final Map<Integer, LoadedFurniture> furnitureByBaseEntityId = new ConcurrentHashMap<>(256, 0.5f);
|
||||
private final Map<Integer, LoadedFurniture> furnitureByInteractionEntityId = new ConcurrentHashMap<>(512, 0.5f);
|
||||
private final Map<Integer, int[]> baseEntity2SubEntities = new ConcurrentHashMap<>(256, 0.5f);
|
||||
|
||||
// Delay furniture cache remove for about 4-5 ticks
|
||||
private static final int DELAYED_TICK = 5;
|
||||
private final IntSet[] delayedRemove = new IntSet[DELAYED_TICK];
|
||||
// Event listeners
|
||||
private final Listener dismountListener;
|
||||
private final FurnitureEventListener furnitureEventListener;
|
||||
@@ -56,9 +49,6 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
this.plugin = plugin;
|
||||
this.furnitureEventListener = new FurnitureEventListener(this);
|
||||
this.dismountListener = VersionHelper.isVersionNewerThan1_20_3() ? new DismountListener1_20_3(this) : new DismountListener1_20(this::handleDismount);
|
||||
for (int i = 0; i < DELAYED_TICK; i++) {
|
||||
this.delayedRemove[i] = new IntOpenHashSet();
|
||||
}
|
||||
instance = this;
|
||||
}
|
||||
|
||||
@@ -171,18 +161,6 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
IntSet first = this.delayedRemove[0];
|
||||
for (int i : first) {
|
||||
// unloaded furniture might be loaded again
|
||||
LoadedFurniture furniture = getLoadedFurnitureByBaseEntityId(i);
|
||||
if (furniture == null)
|
||||
this.baseEntity2SubEntities.remove(i);
|
||||
}
|
||||
first.clear();
|
||||
for (int i = 1; i < DELAYED_TICK; i++) {
|
||||
this.delayedRemove[i - 1] = this.delayedRemove[i];
|
||||
}
|
||||
this.delayedRemove[DELAYED_TICK-1] = first;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -224,12 +202,6 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
return Optional.ofNullable(this.byId.get(id));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public int[] getSubEntityIdsByBaseEntityId(int entityId) {
|
||||
return this.baseEntity2SubEntities.get(entityId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFurnitureBaseEntity(int entityId) {
|
||||
return this.furnitureByBaseEntityId.containsKey(entityId);
|
||||
@@ -253,7 +225,6 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
for (int sub : furniture.interactionEntityIds()) {
|
||||
this.furnitureByInteractionEntityId.remove(sub);
|
||||
}
|
||||
this.delayedRemove[DELAYED_TICK-1].add(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,6 +241,7 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
if (previous != null) return;
|
||||
LoadedFurniture furniture = addNewFurniture(display, customFurniture, getAnchorType(entity, customFurniture));
|
||||
for (Player player : display.getTrackedPlayers()) {
|
||||
this.plugin.adapt(player).furnitureView().computeIfAbsent(furniture.baseEntityId(), k -> new ArrayList<>()).addAll(furniture.subEntityIds());
|
||||
this.plugin.networkManager().sendPacket(player, furniture.spawnPacket());
|
||||
}
|
||||
}
|
||||
@@ -316,7 +288,6 @@ public class BukkitFurnitureManager implements FurnitureManager {
|
||||
private synchronized LoadedFurniture addNewFurniture(ItemDisplay display, CustomFurniture furniture, AnchorType anchorType) {
|
||||
LoadedFurniture loadedFurniture = new LoadedFurniture(display, furniture, anchorType);
|
||||
this.furnitureByBaseEntityId.put(loadedFurniture.baseEntityId(), loadedFurniture);
|
||||
this.baseEntity2SubEntities.put(loadedFurniture.baseEntityId(), loadedFurniture.subEntityIds());
|
||||
for (int entityId : loadedFurniture.interactionEntityIds()) {
|
||||
this.furnitureByInteractionEntityId.put(entityId, loadedFurniture);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,6 @@ public class FurnitureEventListener implements Listener {
|
||||
this.manager.handleEntityUnload(event.getEntity());
|
||||
}
|
||||
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
|
||||
@@ -41,9 +41,9 @@ public class LoadedFurniture {
|
||||
private final WeakReference<Entity> baseEntity;
|
||||
private final int baseEntityId;
|
||||
// includes elements + interactions
|
||||
private final int[] subEntityIds;
|
||||
private final List<Integer> subEntityIds;
|
||||
// interactions
|
||||
private final int[] interactionEntityIds;
|
||||
private final List<Integer> interactionEntityIds;
|
||||
// seats
|
||||
private final Set<Vector3f> occupiedSeats = Collections.synchronizedSet(new HashSet<>());
|
||||
private final Vector<Entity> seats = new Vector<>();
|
||||
@@ -73,14 +73,9 @@ public class LoadedFurniture {
|
||||
interactionEntityIds.add(entityId);
|
||||
this.hitBoxes.put(entityId, hitBox);
|
||||
}
|
||||
this.subEntityIds = new int[entityIds.size()];
|
||||
for (int i = 0; i < entityIds.size(); ++i) {
|
||||
this.subEntityIds[i] = entityIds.get(i);
|
||||
}
|
||||
this.interactionEntityIds = new int[interactionEntityIds.size()];
|
||||
for (int i = 0; i < interactionEntityIds.size(); ++i) {
|
||||
this.interactionEntityIds[i] = interactionEntityIds.get(i);
|
||||
}
|
||||
this.subEntityIds = entityIds;
|
||||
this.interactionEntityIds = interactionEntityIds;
|
||||
this.resetSpawnPackets();
|
||||
}
|
||||
|
||||
private void resetSpawnPackets() {
|
||||
@@ -148,13 +143,6 @@ public class LoadedFurniture {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public Object spawnPacket() {
|
||||
if (this.cachedSpawnPacket == null) {
|
||||
this.resetSpawnPackets();
|
||||
}
|
||||
return this.cachedSpawnPacket;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Entity baseEntity() {
|
||||
Entity entity = baseEntity.get();
|
||||
@@ -235,11 +223,11 @@ public class LoadedFurniture {
|
||||
return baseEntityId;
|
||||
}
|
||||
|
||||
public int[] interactionEntityIds() {
|
||||
public List<Integer> interactionEntityIds() {
|
||||
return interactionEntityIds;
|
||||
}
|
||||
|
||||
public int[] subEntityIds() {
|
||||
public List<Integer> subEntityIds() {
|
||||
return this.subEntityIds;
|
||||
}
|
||||
|
||||
@@ -286,4 +274,8 @@ public class LoadedFurniture {
|
||||
this.addSeatEntity(seatEntity);
|
||||
seatEntity.addPassenger(player);
|
||||
}
|
||||
|
||||
public @NotNull Object spawnPacket() {
|
||||
return cachedSpawnPacket;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.momirealms.craftengine.bukkit.item;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.compatibility.item.NeigeItemsProvider;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.AxeItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BoneMealBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BucketItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.WaterBucketItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.factory.BukkitItemFactory;
|
||||
@@ -50,7 +50,6 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
registerVanillaItemExtraBehavior(AxeItemBehavior.INSTANCE, ItemKeys.AXES);
|
||||
registerVanillaItemExtraBehavior(WaterBucketItemBehavior.INSTANCE, ItemKeys.WATER_BUCKETS);
|
||||
registerVanillaItemExtraBehavior(BucketItemBehavior.INSTANCE, ItemKeys.BUCKET);
|
||||
registerVanillaItemExtraBehavior(BoneMealBehavior.INSTANCE, ItemKeys.BONE_MEAL);
|
||||
}
|
||||
|
||||
private static BukkitItemManager instance;
|
||||
@@ -71,8 +70,15 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
|
||||
@Override
|
||||
public void delayedInit() {
|
||||
Bukkit.getPluginManager().registerEvents(this.itemEventListener, plugin.bootstrap());
|
||||
Bukkit.getPluginManager().registerEvents(this.debugStickListener, plugin.bootstrap());
|
||||
Bukkit.getPluginManager().registerEvents(this.itemEventListener, this.plugin.bootstrap());
|
||||
Bukkit.getPluginManager().registerEvents(this.debugStickListener, this.plugin.bootstrap());
|
||||
this.hookExternalPlugins();
|
||||
}
|
||||
|
||||
private void hookExternalPlugins() {
|
||||
if (this.plugin.isPluginEnabled("NeigeItems")) {
|
||||
registerExternalItemProvider(new NeigeItemsProvider());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -79,7 +79,7 @@ public class BlockItemBehavior extends ItemBehavior {
|
||||
|
||||
BlockPos pos = placeContext.getClickedPos();
|
||||
BlockPos againstPos = placeContext.getAgainstPos();
|
||||
World world = (World) placeContext.getLevel().getHandle();
|
||||
World world = (World) placeContext.getLevel().platformWorld();
|
||||
Location placeLocation = new Location(world, pos.x(), pos.y(), pos.z());
|
||||
|
||||
Block bukkitBlock = world.getBlockAt(placeLocation);
|
||||
@@ -151,7 +151,7 @@ public class BlockItemBehavior extends ItemBehavior {
|
||||
Object blockState = state.customBlockState().handle();
|
||||
Object blockPos = LocationUtils.toBlockPos(context.getClickedPos());
|
||||
Object voxelShape = Reflections.method$CollisionContext$of.invoke(null, player);
|
||||
Object world = Reflections.field$CraftWorld$ServerLevel.get(context.getLevel().getHandle());
|
||||
Object world = Reflections.field$CraftWorld$ServerLevel.get(context.getLevel().platformWorld());
|
||||
boolean defaultReturn = ((!this.checkStatePlacement() || (boolean) Reflections.method$BlockStateBase$canSurvive.invoke(blockState, world, blockPos))
|
||||
&& (boolean) Reflections.method$ServerLevel$checkEntityCollision.invoke(world, blockState, player, voxelShape, blockPos, true));
|
||||
Block block = (Block) Reflections.method$CraftBlock$at.invoke(null, world, blockPos);
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.item.behavior;
|
||||
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
public class BoneMealBehavior extends ItemBehavior {
|
||||
public static final BoneMealBehavior INSTANCE = new BoneMealBehavior();
|
||||
|
||||
@Override
|
||||
public InteractionResult useOnBlock(UseOnContext context) {
|
||||
return super.useOnBlock(context);
|
||||
}
|
||||
|
||||
public static class Factory implements ItemBehaviorFactory {
|
||||
@Override
|
||||
public ItemBehavior create(Pack pack, Path path, Key id, Map<String, Object> arguments) {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,16 +5,17 @@ import net.momirealms.craftengine.core.item.behavior.ItemBehaviors;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
public class BukkitItemBehaviors extends ItemBehaviors {
|
||||
public static final Key EMPTY = Key.from("craftengine:empty");
|
||||
public static final Key BLOCK_ITEM = Key.from("craftengine:block_item");
|
||||
public static final Key ON_LIQUID_BLOCK_ITEM = Key.from("craftengine:liquid_collision_block_item");
|
||||
public static final Key FURNITURE_ITEM = Key.from("craftengine:furniture_item");
|
||||
public static final Key AXE_ITEM = Key.from("craftengine:axe_item");
|
||||
public static final Key WATER_BUCKET_ITEM = Key.from("craftengine:water_bucket_item");
|
||||
public static final Key BUCKET_ITEM = Key.from("craftengine:bucket_item");
|
||||
|
||||
public static void init() {
|
||||
register(EMPTY, (pack, path, args, id) -> EmptyItemBehavior.INSTANCE);
|
||||
register(EMPTY, EmptyItemBehavior.FACTORY);
|
||||
register(BLOCK_ITEM, BlockItemBehavior.FACTORY);
|
||||
register(ON_LIQUID_BLOCK_ITEM, LiquidCollisionBlockItemBehavior.FACTORY);
|
||||
register(FURNITURE_ITEM, FurnitureItemBehavior.FACTORY);
|
||||
register(AXE_ITEM, AxeItemBehavior.FACTORY);
|
||||
register(WATER_BUCKET_ITEM, WaterBucketItemBehavior.FACTORY);
|
||||
|
||||
@@ -77,7 +77,7 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
||||
|
||||
// trigger event
|
||||
org.bukkit.entity.Player bukkitPlayer = (org.bukkit.entity.Player) player.platformPlayer();
|
||||
World world = (World) context.getLevel().getHandle();
|
||||
World world = (World) context.getLevel().platformWorld();
|
||||
|
||||
// get position and rotation for placement
|
||||
Vec3d finalPlacePosition;
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package net.momirealms.craftengine.bukkit.item.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
public class LiquidCollisionBlockItemBehavior extends BlockItemBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
private final int offsetY;
|
||||
|
||||
public LiquidCollisionBlockItemBehavior(Key blockId, int offsetY) {
|
||||
super(blockId);
|
||||
this.offsetY = offsetY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useOnBlock(UseOnContext context) {
|
||||
return use(context.getLevel(), context.getPlayer(), context.getHand());
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult use(World world, Player player, InteractionHand hand) {
|
||||
try {
|
||||
Object blockHitResult = Reflections.method$Item$getPlayerPOVHitResult.invoke(null, world.serverWorld(), player.serverPlayer(), Reflections.instance$ClipContext$Fluid$SOURCE_ONLY);
|
||||
Object blockPos = Reflections.field$BlockHitResul$blockPos.get(blockHitResult);
|
||||
BlockPos above = new BlockPos(Reflections.field$Vec3i$x.getInt(blockPos), Reflections.field$Vec3i$y.getInt(blockPos) + offsetY, Reflections.field$Vec3i$z.getInt(blockPos));
|
||||
Direction direction = Direction.values()[(int) Reflections.method$Direction$ordinal.invoke(Reflections.field$BlockHitResul$direction.get(blockHitResult))];
|
||||
boolean miss = Reflections.field$BlockHitResul$miss.getBoolean(blockHitResult);
|
||||
Vec3d hitPos = LocationUtils.fromVec(Reflections.field$HitResult$location.get(blockHitResult));
|
||||
if (miss) {
|
||||
return super.useOnBlock(new UseOnContext(player, hand, BlockHitResult.miss(hitPos, direction, above)));
|
||||
} else {
|
||||
boolean inside = Reflections.field$BlockHitResul$inside.getBoolean(blockHitResult);
|
||||
return super.useOnBlock(new UseOnContext(player, hand, new BlockHitResult(hitPos, direction, above, inside)));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Error handling use", e);
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory implements ItemBehaviorFactory {
|
||||
@Override
|
||||
public ItemBehavior create(Pack pack, Path path, Key key, Map<String, Object> arguments) {
|
||||
Object id = arguments.get("block");
|
||||
if (id == null) {
|
||||
throw new IllegalArgumentException("Missing required parameter 'block' for on_liquid_block_item behavior");
|
||||
}
|
||||
int offset = MiscUtils.getAsInt(arguments.getOrDefault("y-offset", 1));
|
||||
if (id instanceof Map<?, ?> map) {
|
||||
BukkitBlockManager.instance().parseSection(pack, path, key, MiscUtils.castToMap(map, false));
|
||||
return new LiquidCollisionBlockItemBehavior(key, offset);
|
||||
} else {
|
||||
return new LiquidCollisionBlockItemBehavior(Key.of(id.toString()), offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -299,7 +299,7 @@ public class ComponentItemFactory extends BukkitItemFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemWrapper<ItemStack> merge(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
|
||||
protected ItemWrapper<ItemStack> mergeCopy(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
|
||||
Object itemStack1 = item1.getLiteralObject();
|
||||
Object itemStack2 = item2.getLiteralObject();
|
||||
try {
|
||||
@@ -311,4 +311,17 @@ public class ComponentItemFactory extends BukkitItemFactory {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void merge(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
|
||||
// load previous changes on nms items
|
||||
item1.load();
|
||||
Object itemStack1 = item1.getLiteralObject();
|
||||
Object itemStack2 = item2.getLiteralObject();
|
||||
try {
|
||||
Reflections.method$ItemStack$applyComponents.invoke(itemStack1, Reflections.method$ItemStack$getComponentsPatch.invoke(itemStack2));
|
||||
} catch (Exception e) {
|
||||
plugin.logger().warn("Failed to merge item", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,11 +234,18 @@ public class UniversalItemFactory extends BukkitItemFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemWrapper<ItemStack> merge(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
|
||||
protected ItemWrapper<ItemStack> mergeCopy(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
|
||||
Object itemStack = ItemObject.copy(item2.getLiteralObject());
|
||||
ItemObject.setCustomDataTag(itemStack, TagCompound.clone(ItemObject.getCustomDataTag(item1.getLiteralObject())));
|
||||
// one more step than vanilla
|
||||
TagCompound.merge(ItemObject.getCustomDataTag(itemStack), ItemObject.getCustomDataTag(item2.getLiteralObject()), true, true);
|
||||
return new RTagItemWrapper(new RtagItem(ItemObject.asCraftMirror(itemStack)), item2.count());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void merge(ItemWrapper<ItemStack> item1, ItemWrapper<ItemStack> item2) {
|
||||
// load previous changes on nms items
|
||||
item1.load();
|
||||
TagCompound.merge(ItemObject.getCustomDataTag(item1.getLiteralObject()), ItemObject.getCustomDataTag(item2.getLiteralObject()), true, true);
|
||||
}
|
||||
}
|
||||
@@ -44,8 +44,10 @@ public class DebugAppearanceStateUsageCommand extends BukkitCommandFeature<Comma
|
||||
List<Integer> appearances = blockManager.blockAppearanceArranger().get(baseBlockId);
|
||||
if (appearances == null) return;
|
||||
int i = 0;
|
||||
Component component = Component.text(baseBlockId + ": ");
|
||||
List<Component> children = new ArrayList<>();
|
||||
Component block = Component.text(baseBlockId + ": ");
|
||||
plugin().senderFactory().wrap(context.sender()).sendMessage(block);
|
||||
|
||||
List<Component> batch = new ArrayList<>();
|
||||
for (int appearance : appearances) {
|
||||
Component text = Component.text("|");
|
||||
List<Integer> reals = blockManager.appearanceToRealStates(appearance);
|
||||
@@ -64,11 +66,19 @@ public class DebugAppearanceStateUsageCommand extends BukkitCommandFeature<Comma
|
||||
}
|
||||
text = text.color(NamedTextColor.RED).hoverEvent(HoverEvent.showText(hover.children(hoverChildren)));
|
||||
}
|
||||
children.add(text);
|
||||
batch.add(text);
|
||||
i++;
|
||||
if (batch.size() == 100) {
|
||||
plugin().senderFactory().wrap(context.sender())
|
||||
.sendMessage(Component.text("").children(batch));
|
||||
batch.clear();
|
||||
}
|
||||
}
|
||||
if (!batch.isEmpty()) {
|
||||
plugin().senderFactory().wrap(context.sender())
|
||||
.sendMessage(Component.text("").children(batch));
|
||||
batch.clear();
|
||||
}
|
||||
plugin().senderFactory().wrap(context.sender())
|
||||
.sendMessage(component.children(children));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -44,22 +44,32 @@ public class DebugRealStateUsageCommand extends BukkitCommandFeature<CommandSend
|
||||
List<Integer> reals = blockManager.realBlockArranger().get(baseBlockId);
|
||||
if (reals == null) return;
|
||||
int i = 0;
|
||||
Component component = Component.text(baseBlockId + ": ");
|
||||
List<Component> children = new ArrayList<>();
|
||||
Component block = Component.text(baseBlockId + ": ");
|
||||
plugin().senderFactory().wrap(context.sender()).sendMessage(block);
|
||||
|
||||
List<Component> batch = new ArrayList<>(100);
|
||||
for (int real : reals) {
|
||||
ImmutableBlockState state = blockManager.getImmutableBlockStateUnsafe(real);
|
||||
if (state.isEmpty()) {
|
||||
Component hover = Component.text("craftengine:" + baseBlockId.value() + "_" + i).color(NamedTextColor.GREEN);
|
||||
children.add(Component.text("|").color(NamedTextColor.GREEN).hoverEvent(HoverEvent.showText(hover)));
|
||||
batch.add(Component.text("|").color(NamedTextColor.GREEN).hoverEvent(HoverEvent.showText(hover)));
|
||||
} else {
|
||||
Component hover = Component.text("craftengine:" + baseBlockId.value() + "_" + i).color(NamedTextColor.RED);
|
||||
hover = hover.append(Component.newline()).append(Component.text(state.toString()).color(NamedTextColor.GRAY));
|
||||
children.add(Component.text("|").color(NamedTextColor.RED).hoverEvent(HoverEvent.showText(hover)));
|
||||
batch.add(Component.text("|").color(NamedTextColor.RED).hoverEvent(HoverEvent.showText(hover)));
|
||||
}
|
||||
i++;
|
||||
if (batch.size() == 100) {
|
||||
plugin().senderFactory().wrap(context.sender())
|
||||
.sendMessage(Component.text("").children(batch));
|
||||
batch.clear();
|
||||
}
|
||||
}
|
||||
if (!batch.isEmpty()) {
|
||||
plugin().senderFactory().wrap(context.sender())
|
||||
.sendMessage(Component.text("").children(batch));
|
||||
batch.clear();
|
||||
}
|
||||
plugin().senderFactory().wrap(context.sender())
|
||||
.sendMessage(component.children(children));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.LocationUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
@@ -50,6 +51,8 @@ public class DebugTargetBlockCommand extends BukkitCommandFeature<CommandSender>
|
||||
if (immutableBlockState != null) {
|
||||
sender.sendMessage(Component.text(immutableBlockState.toString()));
|
||||
}
|
||||
ImmutableBlockState dataInCache = plugin().worldManager().getWorld(block.getWorld().getUID()).getBlockStateAtIfLoaded(LocationUtils.toBlockPos(block.getLocation()));
|
||||
sender.sendMessage(Component.text("cache-state: " + !dataInCache.isEmpty()));
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<Object> tags = (Set<Object>) Reflections.field$Holder$Reference$tags.get(holder);
|
||||
|
||||
@@ -125,6 +125,9 @@ public class BukkitNetworkManager implements NetworkManager, Listener {
|
||||
registerNMSPacketConsumer(PacketConsumers.MOVE_ENTITY, Reflections.clazz$ClientboundMoveEntityPacket$Pos);
|
||||
registerNMSPacketConsumer(PacketConsumers.PICK_ITEM_FROM_ENTITY, Reflections.clazz$ServerboundPickItemFromEntityPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.SOUND, Reflections.clazz$ClientboundSoundPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.CHAT, Reflections.clazz$ServerboundChatPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.RENAME_ITEM, Reflections.clazz$ServerboundRenameItemPacket);
|
||||
registerNMSPacketConsumer(PacketConsumers.SIGN_UPDATE, Reflections.clazz$ServerboundSignUpdatePacket);
|
||||
registerByteBufPacketConsumer(PacketConsumers.SECTION_BLOCK_UPDATE, this.packetIds.clientboundSectionBlocksUpdatePacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.BLOCK_UPDATE, this.packetIds.clientboundBlockUpdatePacket());
|
||||
registerByteBufPacketConsumer(PacketConsumers.LEVEL_PARTICLE, this.packetIds.clientboundLevelParticlesPacket());
|
||||
@@ -265,6 +268,28 @@ public class BukkitNetworkManager implements NetworkManager, Listener {
|
||||
this.packetsConsumer.accept(player.serverPlayer(), packet);
|
||||
}
|
||||
|
||||
public void receivePacket(@NotNull NetWorkUser player, Object packet) {
|
||||
Channel channel = player.nettyChannel();
|
||||
if (channel.isOpen()) {
|
||||
List<String> handlerNames = channel.pipeline().names();
|
||||
if (handlerNames.contains("via-encoder")) {
|
||||
channel.pipeline().context("via-decoder").fireChannelRead(packet);
|
||||
} else if (handlerNames.contains("ps_decoder_transformer")) {
|
||||
channel.pipeline().context("ps_decoder_transformer").fireChannelRead(packet);
|
||||
} else if (handlerNames.contains("decompress")) {
|
||||
channel.pipeline().context("decompress").fireChannelRead(packet);
|
||||
} else {
|
||||
if (handlerNames.contains("decrypt")) {
|
||||
channel.pipeline().context("decrypt").fireChannelRead(packet);
|
||||
} else {
|
||||
channel.pipeline().context("splitter").fireChannelRead(packet);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
((ByteBuf) packet).release();
|
||||
}
|
||||
}
|
||||
|
||||
private void injectServerChannel(Channel serverChannel) {
|
||||
ChannelPipeline pipeline = serverChannel.pipeline();
|
||||
ChannelHandler connectionHandler = pipeline.get(CONNECTION_HANDLER_NAME);
|
||||
|
||||
@@ -14,6 +14,7 @@ import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.font.ImageManager;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigManager;
|
||||
import net.momirealms.craftengine.core.plugin.network.ConnectionState;
|
||||
@@ -32,10 +33,9 @@ import org.bukkit.util.RayTraceResult;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PacketConsumers {
|
||||
private static int[] mappings;
|
||||
@@ -344,7 +344,7 @@ public class PacketConsumers {
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundSetCreativeModeSlotPacket", e);
|
||||
}
|
||||
}, (World) player.level().getHandle(), (MCUtils.fastFloor(player.x())) >> 4, (MCUtils.fastFloor(player.z())) >> 4);
|
||||
}, (World) player.level().platformWorld(), (MCUtils.fastFloor(player.x())) >> 4, (MCUtils.fastFloor(player.z())) >> 4);
|
||||
} else {
|
||||
handleSetCreativeSlotPacketOnMainThread(player, packet);
|
||||
}
|
||||
@@ -532,6 +532,7 @@ public class PacketConsumers {
|
||||
int entityId = (int) Reflections.field$ClientboundAddEntityPacket$entityId.get(packet);
|
||||
LoadedFurniture furniture = BukkitFurnitureManager.instance().getLoadedFurnitureByBaseEntityId(entityId);
|
||||
if (furniture != null) {
|
||||
user.furnitureView().computeIfAbsent(furniture.baseEntityId(), k -> new ArrayList<>()).addAll(furniture.subEntityIds());
|
||||
user.sendPacket(furniture.spawnPacket(), false);
|
||||
}
|
||||
}
|
||||
@@ -566,7 +567,7 @@ public class PacketConsumers {
|
||||
try {
|
||||
IntList intList = (IntList) Reflections.field$ClientboundRemoveEntitiesPacket$entityIds.get(packet);
|
||||
for (int i = 0, size = intList.size(); i < size; i++) {
|
||||
int[] entities = BukkitFurnitureManager.instance().getSubEntityIdsByBaseEntityId(intList.getInt(i));
|
||||
List<Integer> entities = user.furnitureView().remove(intList.getInt(i));
|
||||
if (entities == null) continue;
|
||||
for (int entityId : entities) {
|
||||
intList.add(entityId);
|
||||
@@ -661,4 +662,92 @@ public class PacketConsumers {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ClientboundSoundPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
// we handle it on packet level to prevent it from being captured by plugins (most are chat plugins)
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> CHAT = (user, event, packet) -> {
|
||||
try {
|
||||
String message = (String) Reflections.field$ServerboundChatPacket$message.get(packet);
|
||||
if (message != null && !message.isEmpty()) {
|
||||
ImageManager manager = CraftEngine.instance().imageManager();
|
||||
if (!manager.isDefaultFontInUse()) return;
|
||||
runIfContainsIllegalCharacter(message, manager, (s) -> {
|
||||
event.setCancelled(true);
|
||||
try {
|
||||
Object newPacket = Reflections.constructor$ServerboundChatPacket.newInstance(
|
||||
s,
|
||||
Reflections.field$ServerboundChatPacket$timeStamp.get(packet),
|
||||
Reflections.field$ServerboundChatPacket$salt.get(packet),
|
||||
Reflections.field$ServerboundChatPacket$signature.get(packet),
|
||||
Reflections.field$ServerboundChatPacket$lastSeenMessages.get(packet)
|
||||
);
|
||||
user.receivePacket(newPacket);
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to create replaced chat packet", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundChatPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
// we handle it on packet level to prevent it from being captured by plugins
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> RENAME_ITEM = (user, event, packet) -> {
|
||||
try {
|
||||
String message = (String) Reflections.field$ServerboundRenameItemPacket$name.get(packet);
|
||||
if (message != null && !message.isEmpty()) {
|
||||
ImageManager manager = CraftEngine.instance().imageManager();
|
||||
if (!manager.isDefaultFontInUse()) return;
|
||||
runIfContainsIllegalCharacter(message, manager, (s) -> {
|
||||
try {
|
||||
Reflections.field$ServerboundRenameItemPacket$name.set(packet, s);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
CraftEngine.instance().logger().warn("Failed to replace chat", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundRenameItemPacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
// we handle it on packet level to prevent it from being captured by plugins
|
||||
public static final TriConsumer<NetWorkUser, NMSPacketEvent, Object> SIGN_UPDATE = (user, event, packet) -> {
|
||||
try {
|
||||
String[] lines = (String[]) Reflections.field$ServerboundSignUpdatePacket$lines.get(packet);
|
||||
ImageManager manager = CraftEngine.instance().imageManager();
|
||||
if (!manager.isDefaultFontInUse()) return;
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String line = lines[i];
|
||||
if (line != null && !line.isEmpty()) {
|
||||
try {
|
||||
int lineIndex = i;
|
||||
runIfContainsIllegalCharacter(line, manager, (s) -> lines[lineIndex] = s);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
CraftEngine.instance().logger().warn("Failed to handle ServerboundSignUpdatePacket", e);
|
||||
}
|
||||
};
|
||||
|
||||
private static void runIfContainsIllegalCharacter(String string, ImageManager manager, Consumer<String> callback) {
|
||||
char[] chars = string.toCharArray();
|
||||
int[] codepoints = CharacterUtils.charsToCodePoints(chars);
|
||||
int[] newCodepoints = new int[codepoints.length];
|
||||
boolean hasIllegal = false;
|
||||
for (int i = 0; i < codepoints.length; i++) {
|
||||
int codepoint = codepoints[i];
|
||||
if (!manager.isIllegalCharacter(codepoint)) {
|
||||
newCodepoints[i] = codepoint;
|
||||
} else {
|
||||
newCodepoints[i] = '*';
|
||||
hasIllegal = true;
|
||||
}
|
||||
}
|
||||
if (hasIllegal) {
|
||||
callback.accept(new String(newCodepoints, 0, newCodepoints.length));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,20 +16,23 @@ import net.momirealms.craftengine.core.plugin.network.ConnectionState;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.Vec3d;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.*;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.util.RayTraceResult;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class BukkitServerPlayer extends Player {
|
||||
private final Channel channel;
|
||||
@@ -60,6 +63,8 @@ public class BukkitServerPlayer extends Player {
|
||||
|
||||
private Key lastUsedRecipe = null;
|
||||
|
||||
private Map<Integer, List<Integer>> furnitureView = new ConcurrentHashMap<>();
|
||||
|
||||
public BukkitServerPlayer(BukkitCraftEngine plugin, Channel channel) {
|
||||
this.channel = channel;
|
||||
this.plugin = plugin;
|
||||
@@ -201,11 +206,41 @@ public class BukkitServerPlayer extends Player {
|
||||
platformPlayer().closeInventory();
|
||||
}
|
||||
|
||||
// TODO DO NOT USE BUKKIT API
|
||||
@Override
|
||||
public BlockHitResult rayTrace(double distance, FluidCollisionRule collisionRule) {
|
||||
RayTraceResult result = platformPlayer().rayTraceBlocks(distance, FluidUtils.toCollisionRule(collisionRule));
|
||||
if (result == null) {
|
||||
Location eyeLocation = platformPlayer().getEyeLocation();
|
||||
Location targetLocation = eyeLocation.clone();
|
||||
targetLocation.add(eyeLocation.getDirection().multiply(distance));
|
||||
return BlockHitResult.miss(new Vec3d(eyeLocation.getX(), eyeLocation.getY(), eyeLocation.getZ()),
|
||||
Direction.getApproximateNearest(eyeLocation.getX() - targetLocation.getX(), eyeLocation.getY() - targetLocation.getY(), eyeLocation.getZ() - targetLocation.getZ()),
|
||||
new BlockPos(targetLocation.getBlockX(), targetLocation.getBlockY(), targetLocation.getBlockZ())
|
||||
);
|
||||
} else {
|
||||
Vector hitPos = result.getHitPosition();
|
||||
Block hitBlock = result.getHitBlock();
|
||||
Location hitBlockLocation = hitBlock.getLocation();
|
||||
return new BlockHitResult(
|
||||
new Vec3d(hitPos.getX(), hitPos.getY(), hitPos.getZ()),
|
||||
DirectionUtils.toDirection(result.getHitBlockFace()),
|
||||
new BlockPos(hitBlockLocation.getBlockX(), hitBlockLocation.getBlockY(), hitBlockLocation.getBlockZ()),
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(Object packet, boolean immediately) {
|
||||
this.plugin.networkManager().sendPacket(this, packet, immediately);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receivePacket(Object packet) {
|
||||
this.plugin.networkManager().receivePacket(this, packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionState decoderState() {
|
||||
return decoderState;
|
||||
@@ -553,6 +588,11 @@ public class BukkitServerPlayer extends Player {
|
||||
return playerRef.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Integer, List<Integer>> furnitureView() {
|
||||
return this.furnitureView;
|
||||
}
|
||||
|
||||
public void setResendSound() {
|
||||
resentSoundTick = gameTicks();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.core.world.FluidCollisionRule;
|
||||
import org.bukkit.FluidCollisionMode;
|
||||
|
||||
public class FluidUtils {
|
||||
|
||||
private FluidUtils() {}
|
||||
|
||||
public static FluidCollisionMode toCollisionRule(FluidCollisionRule rule) {
|
||||
switch (rule) {
|
||||
case NONE -> {
|
||||
return FluidCollisionMode.NEVER;
|
||||
}
|
||||
case ALWAYS -> {
|
||||
return FluidCollisionMode.ALWAYS;
|
||||
}
|
||||
case SOURCE_ONLY -> {
|
||||
return FluidCollisionMode.SOURCE_ONLY;
|
||||
}
|
||||
}
|
||||
return FluidCollisionMode.NEVER;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,14 @@ public class LocationUtils {
|
||||
return new Vec3d(loc.getX(), loc.getY(), loc.getZ());
|
||||
}
|
||||
|
||||
public static Vec3d fromVec(Object vec) throws ReflectiveOperationException {
|
||||
return new Vec3d(
|
||||
Reflections.field$Vec3$x.getDouble(vec),
|
||||
Reflections.field$Vec3$y.getDouble(vec),
|
||||
Reflections.field$Vec3$z.getDouble(vec)
|
||||
);
|
||||
}
|
||||
|
||||
public static Object toBlockPos(BlockPos pos) {
|
||||
try {
|
||||
return Reflections.constructor$BlockPos.newInstance(pos.x(), pos.y(), pos.z());
|
||||
@@ -21,6 +29,14 @@ public class LocationUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static Object above(Object blockPos) throws ReflectiveOperationException {
|
||||
return toBlockPos(
|
||||
Reflections.field$Vec3i$x.getInt(blockPos),
|
||||
Reflections.field$Vec3i$y.getInt(blockPos) + 1,
|
||||
Reflections.field$Vec3i$z.getInt(blockPos)
|
||||
);
|
||||
}
|
||||
|
||||
public static Object toBlockPos(int x, int y, int z) {
|
||||
try {
|
||||
return Reflections.constructor$BlockPos.newInstance(x, y, z);
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.Location;
|
||||
@@ -26,6 +27,7 @@ import sun.misc.Unsafe;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.lang.reflect.*;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -134,9 +136,7 @@ public class Reflections {
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$ClientboundSystemChatPacket = requireNonNull(
|
||||
ReflectionUtils.getConstructor(
|
||||
clazz$ClientboundSystemChatPacket, clazz$Component, boolean.class
|
||||
)
|
||||
ReflectionUtils.getConstructor(clazz$ClientboundSystemChatPacket, clazz$Component, boolean.class)
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundSystemChatPacket$overlay = requireNonNull(
|
||||
@@ -189,6 +189,11 @@ public class Reflections {
|
||||
clazz$ClientboundSystemChatPacket, clazz$Component, 0
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundSystemChatPacket$adventure$content =
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundSystemChatPacket, Component.class, 0
|
||||
);
|
||||
|
||||
public static final Field field$ClientboundSystemChatPacket$text =
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ClientboundSystemChatPacket, String.class, 0
|
||||
@@ -1455,6 +1460,12 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$Direction$ordinal = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$Direction, new String[]{"ordinal"}
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$Direction$values = requireNonNull(
|
||||
ReflectionUtils.getStaticMethod(
|
||||
clazz$Direction, clazz$Direction.arrayType()
|
||||
@@ -3326,6 +3337,7 @@ public class Reflections {
|
||||
public static final Object instance$Blocks$STONE;
|
||||
public static final Object instance$Blocks$STONE$defaultState;
|
||||
public static final Object instance$Blocks$FIRE;
|
||||
public static final Object instance$Blocks$ICE;
|
||||
|
||||
static {
|
||||
try {
|
||||
@@ -3337,6 +3349,8 @@ public class Reflections {
|
||||
Object stone = method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "stone");
|
||||
instance$Blocks$STONE = method$Registry$get.invoke(instance$BuiltInRegistries$BLOCK, stone);
|
||||
instance$Blocks$STONE$defaultState = method$Block$defaultBlockState.invoke(instance$Blocks$STONE);
|
||||
Object ice = method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "ice");
|
||||
instance$Blocks$ICE = method$Registry$get.invoke(instance$BuiltInRegistries$BLOCK, ice);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -3862,11 +3876,17 @@ public class Reflections {
|
||||
);
|
||||
|
||||
public static final Object instance$Fluids$WATER;
|
||||
public static final Object instance$Fluids$LAVA;
|
||||
public static final Object instance$Fluids$EMPTY;
|
||||
|
||||
static {
|
||||
try {
|
||||
Object waterId = method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "water");
|
||||
instance$Fluids$WATER = method$Registry$get.invoke(instance$BuiltInRegistries$FLUID, waterId);
|
||||
Object lavaId = method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "lava");
|
||||
instance$Fluids$LAVA = method$Registry$get.invoke(instance$BuiltInRegistries$FLUID, lavaId);
|
||||
Object emptyId = method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "empty");
|
||||
instance$Fluids$EMPTY = method$Registry$get.invoke(instance$BuiltInRegistries$FLUID, emptyId);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -5015,4 +5035,170 @@ public class Reflections {
|
||||
clazz$ItemStack, clazz$Item
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$BlockHitResult = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.phys.BlockHitResult"),
|
||||
BukkitReflectionUtils.assembleMCClass("world.phys.MovingObjectPositionBlock")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ClipContext$Fluid = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.level.ClipContext$Fluid"),
|
||||
BukkitReflectionUtils.assembleMCClass("world.level.RayTrace$FluidCollisionOption")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$ClipContext$Fluid$values = requireNonNull(
|
||||
ReflectionUtils.getStaticMethod(
|
||||
clazz$ClipContext$Fluid, clazz$ClipContext$Fluid.arrayType()
|
||||
)
|
||||
);
|
||||
|
||||
public static final Object instance$ClipContext$Fluid$NONE;
|
||||
public static final Object instance$ClipContext$Fluid$SOURCE_ONLY;
|
||||
public static final Object instance$ClipContext$Fluid$ANY;
|
||||
|
||||
static {
|
||||
try {
|
||||
Object[] values = (Object[]) method$ClipContext$Fluid$values.invoke(null);
|
||||
instance$ClipContext$Fluid$NONE = values[0];
|
||||
instance$ClipContext$Fluid$SOURCE_ONLY = values[1];
|
||||
instance$ClipContext$Fluid$ANY = values[2];
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Method method$Item$getPlayerPOVHitResult = requireNonNull(
|
||||
ReflectionUtils.getDeclaredMethod(
|
||||
clazz$Item, clazz$BlockHitResult, clazz$Level, clazz$Player, clazz$ClipContext$Fluid
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$BlockHitResult$withPosition = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$BlockHitResult, clazz$BlockHitResult, clazz$BlockPos
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$BlockHitResul$blockPos = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$BlockHitResult, clazz$BlockPos, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$BlockHitResul$direction = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$BlockHitResult, clazz$Direction, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$BlockHitResul$miss = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$BlockHitResult, boolean.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$BlockHitResul$inside = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$BlockHitResult, boolean.class, 1
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$HitResult = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.phys.HitResult"),
|
||||
BukkitReflectionUtils.assembleMCClass("world.phys.MovingObjectPosition")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$HitResult$location = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$HitResult, clazz$Vec3, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$MessageSignature = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.chat.MessageSignature")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$LastSeenMessages$Update = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.chat.LastSeenMessages$Update"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.chat.LastSeenMessages$b")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ServerboundChatPacket = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundChatPacket"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.PacketPlayInChat")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Constructor<?> constructor$ServerboundChatPacket = requireNonNull(
|
||||
ReflectionUtils.getConstructor(
|
||||
clazz$ServerboundChatPacket, String.class, Instant.class, long.class, clazz$MessageSignature, clazz$LastSeenMessages$Update
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ServerboundChatPacket$message = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ServerboundChatPacket, String.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ServerboundChatPacket$timeStamp = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ServerboundChatPacket, Instant.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ServerboundChatPacket$salt = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ServerboundChatPacket, long.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ServerboundChatPacket$signature = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ServerboundChatPacket, clazz$MessageSignature, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ServerboundChatPacket$lastSeenMessages = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ServerboundChatPacket, clazz$LastSeenMessages$Update, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ServerboundRenameItemPacket = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundRenameItemPacket"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.PacketPlayInItemName")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ServerboundRenameItemPacket$name = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ServerboundRenameItemPacket, String.class, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$ServerboundSignUpdatePacket = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.ServerboundSignUpdatePacket"),
|
||||
BukkitReflectionUtils.assembleMCClass("network.protocol.game.PacketPlayInUpdateSign")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ServerboundSignUpdatePacket$lines = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$ServerboundSignUpdatePacket, String[].class, 0
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public class BukkitCEWorld extends CEWorld {
|
||||
@Override
|
||||
public void tick() {
|
||||
if (ConfigManager.enableLightSystem()) {
|
||||
LightUtils.updateChunkLight((org.bukkit.World) world.getHandle(), SectionPosUtils.toMap(super.updatedSectionPositions, world.worldHeight().getMinSection() - 1, world.worldHeight().getMaxSection() + 1));
|
||||
LightUtils.updateChunkLight((org.bukkit.World) world.platformWorld(), SectionPosUtils.toMap(super.updatedSectionPositions, world.worldHeight().getMinSection() - 1, world.worldHeight().getMaxSection() + 1));
|
||||
super.updatedSectionPositions.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.world;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.util.EntityUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.ItemUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
@@ -28,36 +29,45 @@ public class BukkitWorld implements World {
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.World getHandle() {
|
||||
public org.bukkit.World platformWorld() {
|
||||
return world.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object serverWorld() {
|
||||
try {
|
||||
return Reflections.field$CraftWorld$ServerLevel.get(platformWorld());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to get server world", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldHeight worldHeight() {
|
||||
if (this.worldHeight == null) {
|
||||
this.worldHeight = WorldHeight.create(getHandle().getMinHeight(), getHandle().getMaxHeight() - getHandle().getMinHeight());
|
||||
this.worldHeight = WorldHeight.create(platformWorld().getMinHeight(), platformWorld().getMaxHeight() - platformWorld().getMinHeight());
|
||||
}
|
||||
return this.worldHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldBlock getBlockAt(int x, int y, int z) {
|
||||
return new BukkitWorldBlock(getHandle().getBlockAt(x, y, z));
|
||||
return new BukkitWorldBlock(platformWorld().getBlockAt(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return getHandle().getName();
|
||||
return platformWorld().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path directory() {
|
||||
return getHandle().getWorldFolder().toPath();
|
||||
return platformWorld().getWorldFolder().toPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID uuid() {
|
||||
return getHandle().getUID();
|
||||
return platformWorld().getUID();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,16 +75,16 @@ public class BukkitWorld implements World {
|
||||
ItemStack itemStack = (ItemStack) item.load();
|
||||
if (ItemUtils.isEmpty(itemStack)) return;
|
||||
if (VersionHelper.isVersionNewerThan1_21_2()) {
|
||||
getHandle().dropItemNaturally(new Location(null, location.x(), location.y(), location.z()), (ItemStack) item.getItem());
|
||||
platformWorld().dropItemNaturally(new Location(null, location.x(), location.y(), location.z()), (ItemStack) item.getItem());
|
||||
} else {
|
||||
getHandle().dropItemNaturally(new Location(null, location.x() - 0.5, location.y() - 0.5, location.z() - 0.5), (ItemStack) item.getItem());
|
||||
platformWorld().dropItemNaturally(new Location(null, location.x() - 0.5, location.y() - 0.5, location.z() - 0.5), (ItemStack) item.getItem());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropExp(Vec3d location, int amount) {
|
||||
if (amount <= 0) return;
|
||||
EntityUtils.spawnEntity(getHandle(), new Location(getHandle(), location.x(), location.y(), location.z()), EntityType.EXPERIENCE_ORB, (e) -> {
|
||||
EntityUtils.spawnEntity(platformWorld(), new Location(platformWorld(), location.x(), location.y(), location.z()), EntityType.EXPERIENCE_ORB, (e) -> {
|
||||
ExperienceOrb orb = (ExperienceOrb) e;
|
||||
orb.setExperience(amount);
|
||||
});
|
||||
@@ -82,6 +92,6 @@ public class BukkitWorld implements World {
|
||||
|
||||
@Override
|
||||
public void playBlockSound(Vec3d location, Key sound, float volume, float pitch) {
|
||||
getHandle().playSound(new Location(null, location.x(), location.y(), location.z()), sound.toString(), SoundCategory.BLOCKS, volume, pitch);
|
||||
platformWorld().playSound(new Location(null, location.x(), location.y(), location.z()), sound.toString(), SoundCategory.BLOCKS, volume, pitch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.Map;
|
||||
|
||||
public class BlockBehaviors {
|
||||
public static final Key EMPTY = Key.from("craftengine:empty");
|
||||
|
||||
public static void register(Key key, BlockBehaviorFactory factory) {
|
||||
Holder.Reference<BlockBehaviorFactory> holder = ((WritableRegistry<BlockBehaviorFactory>) BuiltInRegistries.BLOCK_BEHAVIOR_FACTORY)
|
||||
|
||||
@@ -5,7 +5,6 @@ import net.momirealms.craftengine.core.plugin.Reloadable;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigSectionParser;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface FurnitureManager extends Reloadable, ConfigSectionParser {
|
||||
@@ -25,8 +24,5 @@ public interface FurnitureManager extends Reloadable, ConfigSectionParser {
|
||||
|
||||
Optional<CustomFurniture> getFurniture(Key id);
|
||||
|
||||
@Nullable
|
||||
int[] getSubEntityIdsByBaseEntityId(int entityId);
|
||||
|
||||
boolean isFurnitureBaseEntity(int entityId);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@ import net.momirealms.craftengine.core.entity.Entity;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.FluidCollisionRule;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class Player extends Entity implements NetWorkUser {
|
||||
@@ -68,4 +70,6 @@ public abstract class Player extends Entity implements NetWorkUser {
|
||||
public abstract void giveItem(Item<?> item);
|
||||
|
||||
public abstract void closeInventory();
|
||||
|
||||
public abstract BlockHitResult rayTrace(double distance, FluidCollisionRule collisionRule);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.momirealms.craftengine.core.font;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@@ -19,6 +20,10 @@ public class Font {
|
||||
return this.idToCodepoint.containsKey(codepoint);
|
||||
}
|
||||
|
||||
public Collection<Integer> codepointsInUse() {
|
||||
return Collections.unmodifiableCollection(this.idToCodepoint.keySet());
|
||||
}
|
||||
|
||||
public BitmapImage getImageByCodepoint(int codepoint) {
|
||||
return this.idToCodepoint.get(codepoint);
|
||||
}
|
||||
|
||||
@@ -13,11 +13,18 @@ import java.util.function.BiFunction;
|
||||
|
||||
public interface ImageManager extends Reloadable, ConfigSectionParser {
|
||||
String CONFIG_SECTION_NAME = "images";
|
||||
Key DEFAULT_FONT = Key.of("minecraft:default");
|
||||
|
||||
default String sectionId() {
|
||||
return CONFIG_SECTION_NAME;
|
||||
}
|
||||
|
||||
void delayedLoad();
|
||||
|
||||
boolean isDefaultFontInUse();
|
||||
|
||||
boolean isIllegalCharacter(int codepoint);
|
||||
|
||||
Collection<Font> fontsInUse();
|
||||
|
||||
Optional<BitmapImage> bitmapImageByCodepoint(Key font, int codepoint);
|
||||
|
||||
@@ -18,6 +18,7 @@ public class ImageManagerImpl implements ImageManager {
|
||||
private final HashMap<Key, Font> fonts = new HashMap<>();
|
||||
// namespace:id image
|
||||
private final HashMap<Key, BitmapImage> images = new HashMap<>();
|
||||
private final Set<Integer> illegalChars = new HashSet<>();
|
||||
|
||||
private OffsetFont offsetFont;
|
||||
|
||||
@@ -36,6 +37,24 @@ public class ImageManagerImpl implements ImageManager {
|
||||
public void unload() {
|
||||
this.fonts.clear();
|
||||
this.images.clear();
|
||||
this.illegalChars.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delayedLoad() {
|
||||
Optional.ofNullable(this.fonts.get(DEFAULT_FONT)).ifPresent(font -> {
|
||||
this.illegalChars.addAll(font.codepointsInUse());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDefaultFontInUse() {
|
||||
return !this.illegalChars.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIllegalCharacter(int codepoint) {
|
||||
return this.illegalChars.contains(codepoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -280,7 +280,13 @@ public class AbstractItem<W extends ItemWrapper<I>, I> implements Item<I> {
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Override
|
||||
public Item<I> merge(Item<?> another) {
|
||||
return new AbstractItem<>(this.factory, this.factory.merge(this.item, ((AbstractItem) another).item));
|
||||
public Item<I> mergeCopy(Item<?> another) {
|
||||
return new AbstractItem<>(this.factory, this.factory.mergeCopy(this.item, ((AbstractItem) another).item));
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Override
|
||||
public void merge(Item<I> another) {
|
||||
this.factory.merge(this.item, ((AbstractItem) another).item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
|
||||
protected static final List<Key> VANILLA_ITEMS = new ArrayList<>();
|
||||
protected static final Map<Key, List<Holder<Key>>> VANILLA_ITEM_TAGS = new HashMap<>();
|
||||
|
||||
protected final Map<String, ExternalItemProvider<I>> externalItemProviders = new HashMap<>();
|
||||
protected final Map<String, Function<Object, ItemModifier<I>>> dataFunctions = new HashMap<>();
|
||||
protected final Map<Key, CustomItem<I>> customItems = new HashMap<>();
|
||||
protected final Map<Key, List<Holder<Key>>> customItemTags;
|
||||
@@ -47,6 +48,18 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExternalItemProvider<I> getExternalItemProvider(String name) {
|
||||
return this.externalItemProviders.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerExternalItemProvider(ExternalItemProvider<I> externalItemProvider) {
|
||||
if (this.externalItemProviders.containsKey(externalItemProvider.plugin())) return false;
|
||||
this.externalItemProviders.put(externalItemProvider.plugin(), externalItemProvider);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload() {
|
||||
super.clearModelsToGenerate();
|
||||
@@ -165,6 +178,13 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
|
||||
}
|
||||
|
||||
private void registerFunctions() {
|
||||
registerDataFunction((obj) -> {
|
||||
Map<String, Object> data = MiscUtils.castToMap(obj, false);
|
||||
String plugin = data.get("plugin").toString();
|
||||
String id = data.get("id").toString();
|
||||
ExternalItemProvider<I> provider = AbstractItemManager.this.getExternalItemProvider(plugin);
|
||||
return new ExternalModifier<>(id, Objects.requireNonNull(provider, "Item provider " + plugin + " not found"));
|
||||
}, "external");
|
||||
registerDataFunction((obj) -> {
|
||||
String name = obj.toString();
|
||||
return new DisplayNameModifier<>(name);
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package net.momirealms.craftengine.core.item;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface ExternalItemProvider<I> {
|
||||
|
||||
String plugin();
|
||||
|
||||
@Nullable
|
||||
I build(String id, ItemBuildContext context);
|
||||
}
|
||||
@@ -117,5 +117,7 @@ public interface Item<I> {
|
||||
|
||||
Object getLiteralObject();
|
||||
|
||||
Item<I> merge(Item<?> another);
|
||||
Item<I> mergeCopy(Item<?> another);
|
||||
|
||||
void merge(Item<I> another);
|
||||
}
|
||||
|
||||
@@ -112,5 +112,7 @@ public abstract class ItemFactory<P extends Plugin, W extends ItemWrapper<I>, I>
|
||||
|
||||
protected abstract Optional<Integer> repairCost(ItemWrapper<I> item);
|
||||
|
||||
protected abstract ItemWrapper<I> merge(ItemWrapper<I> item1, ItemWrapper<I> item2);
|
||||
protected abstract ItemWrapper<I> mergeCopy(ItemWrapper<I> item1, ItemWrapper<I> item2);
|
||||
|
||||
protected abstract void merge(ItemWrapper<I> item1, ItemWrapper<I> item2);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,10 @@ public interface ItemManager<T> extends Reloadable, ModelGenerator, ConfigSectio
|
||||
|
||||
Key customItemId(T itemStack);
|
||||
|
||||
ExternalItemProvider<T> getExternalItemProvider(String name);
|
||||
|
||||
boolean registerExternalItemProvider(ExternalItemProvider<T> externalItemProvider);
|
||||
|
||||
Optional<CustomItem<T>> getCustomItem(Key key);
|
||||
|
||||
Optional<List<ItemBehavior>> getItemBehavior(Key key);
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
package net.momirealms.craftengine.core.item.behavior;
|
||||
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
public class EmptyItemBehavior extends ItemBehavior {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
public static final EmptyItemBehavior INSTANCE = new EmptyItemBehavior();
|
||||
|
||||
public static class Factory implements ItemBehaviorFactory {
|
||||
|
||||
@Override
|
||||
public ItemBehavior create(Pack pack, Path path, Key id, Map<String, Object> arguments) {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
public class ItemBehaviors {
|
||||
public static final Key EMPTY = Key.from("craftengine:empty");
|
||||
|
||||
public static void register(Key key, ItemBehaviorFactory factory) {
|
||||
Holder.Reference<ItemBehaviorFactory> holder = ((WritableRegistry<ItemBehaviorFactory>) BuiltInRegistries.ITEM_BEHAVIOR_FACTORY)
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package net.momirealms.craftengine.core.item.modifier;
|
||||
|
||||
import net.momirealms.craftengine.core.item.ExternalItemProvider;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
|
||||
public class ExternalModifier<I> implements ItemModifier<I> {
|
||||
private final String id;
|
||||
private final ExternalItemProvider<I> provider;
|
||||
|
||||
public ExternalModifier(String id, ExternalItemProvider<I> provider) {
|
||||
this.id = id;
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "external";
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void apply(Item<I> item, ItemBuildContext context) {
|
||||
I another = this.provider.build(id, context);
|
||||
if (another == null) {
|
||||
CraftEngine.instance().logger().warn("'" + id + "' could not be found in " + provider.plugin());
|
||||
return;
|
||||
}
|
||||
Item<I> anotherWrapped = (Item<I>) CraftEngine.instance().itemManager().wrap(another);
|
||||
item.merge(anotherWrapped);
|
||||
}
|
||||
}
|
||||
@@ -96,7 +96,7 @@ public class CustomSmithingTransformRecipe<T> implements Recipe<T> {
|
||||
Item<T> wrappedResult = (Item<T>) CraftEngine.instance().itemManager().wrap(result);
|
||||
Item<T> finalResult = wrappedResult;
|
||||
if (this.mergeComponents) {
|
||||
finalResult = base.merge(wrappedResult);
|
||||
finalResult = base.mergeCopy(wrappedResult);
|
||||
}
|
||||
for (ItemDataProcessor processor : this.processors) {
|
||||
processor.accept(base, wrappedResult, finalResult);
|
||||
|
||||
@@ -320,14 +320,17 @@ public abstract class AbstractPackManager implements PackManager {
|
||||
plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/block/custom/stripped_palm_log.png");
|
||||
plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/block/custom/stripped_palm_log_top.png");
|
||||
plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/block/custom/palm_leaves.png");
|
||||
// fairy flower
|
||||
plugin.saveResource("resources/default/configuration/fairy_flower.yml");
|
||||
// plants
|
||||
plugin.saveResource("resources/default/configuration/plants.yml");
|
||||
plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/block/custom/fairy_flower_1.png");
|
||||
plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/block/custom/fairy_flower_2.png");
|
||||
plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/block/custom/fairy_flower_3.png");
|
||||
plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/block/custom/fairy_flower_4.png");
|
||||
plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/block/custom/reed.png");
|
||||
plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/item/custom/fairy_flower.png");
|
||||
plugin.saveResource("resources/default/resourcepack/assets/minecraft/textures/item/custom/reed.png");
|
||||
plugin.saveResource("resources/default/resourcepack/assets/minecraft/models/block/custom/fairy_flower_1.json");
|
||||
plugin.saveResource("resources/default/resourcepack/assets/minecraft/models/block/custom/reed.json");
|
||||
// furniture
|
||||
plugin.saveResource("resources/default/configuration/furniture.yml");
|
||||
plugin.saveResource("resources/default/resourcepack/assets/minecraft/models/item/custom/table_lamp.json");
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package net.momirealms.craftengine.core.pack.conflict.resolution;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.GsonHelper;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
public class MergeAltasResolution implements Resolution {
|
||||
public static final Factory FACTORY = new Factory();
|
||||
public static final MergeAltasResolution INSTANCE = new MergeAltasResolution();
|
||||
|
||||
@Override
|
||||
public void run(Path existing, Path conflict) {
|
||||
try {
|
||||
JsonObject j1 = GsonHelper.readJsonFile(existing).getAsJsonObject();
|
||||
JsonObject j2 = GsonHelper.readJsonFile(conflict).getAsJsonObject();
|
||||
JsonObject j3 = new JsonObject();
|
||||
JsonArray ja1 = j1.getAsJsonArray("sources");
|
||||
JsonArray ja2 = j2.getAsJsonArray("sources");
|
||||
JsonArray ja3 = new JsonArray();
|
||||
HashSet<String> elements = new HashSet<>();
|
||||
for (JsonElement je : ja1) {
|
||||
if (elements.add(je.getAsString())) {
|
||||
ja3.add(je);
|
||||
}
|
||||
}
|
||||
for (JsonElement je : ja2) {
|
||||
if (elements.add(je.getAsString())) {
|
||||
ja3.add(je);
|
||||
}
|
||||
}
|
||||
j3.add("sources", ja3);
|
||||
GsonHelper.writeJsonFile(j3, existing);
|
||||
} catch (IOException e) {
|
||||
CraftEngine.instance().logger().severe("Failed to merge json when resolving file conflicts", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key type() {
|
||||
return Resolutions.MERGE_ATLAS;
|
||||
}
|
||||
|
||||
public static class Factory implements ResolutionFactory {
|
||||
|
||||
@Override
|
||||
public Resolution create(Map<String, Object> arguments) {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import java.util.Map;
|
||||
public class Resolutions {
|
||||
public static final Key RETAIN_MATCHING = Key.of("craftengine:retain_matching");
|
||||
public static final Key MERGE_JSON = Key.of("craftengine:merge_json");
|
||||
public static final Key MERGE_ATLAS = Key.of("craftengine:merge_atlas");
|
||||
public static final Key CONDITIONAL = Key.of("craftengine:conditional");
|
||||
public static final Key MERGE_PACK_MCMETA = Key.of("craftengine:merge_pack_mcmeta");
|
||||
|
||||
@@ -20,6 +21,7 @@ public class Resolutions {
|
||||
register(MERGE_JSON, MergeJsonResolution.FACTORY);
|
||||
register(CONDITIONAL, ConditionalResolution.FACTORY);
|
||||
register(MERGE_PACK_MCMETA, MergePackMcMetaResolution.FACTORY);
|
||||
register(MERGE_ATLAS, MergeAltasResolution.FACTORY);
|
||||
}
|
||||
|
||||
public static void register(Key key, ResolutionFactory factory) {
|
||||
|
||||
@@ -106,6 +106,7 @@ public abstract class CraftEngine implements Plugin {
|
||||
this.blockManager.delayedLoad();
|
||||
this.itemBrowserManager.delayedLoad();
|
||||
this.soundManager.delayedLoad();
|
||||
this.imageManager.delayedLoad();
|
||||
if (ConfigManager.debug()) {
|
||||
this.debugger = (s) -> logger.info("[Debug] " + s.get());
|
||||
} else {
|
||||
@@ -126,11 +127,11 @@ public abstract class CraftEngine implements Plugin {
|
||||
// delay the reload so other plugins can register some parsers
|
||||
this.scheduler.sync().runDelayed(() -> {
|
||||
this.registerParsers();
|
||||
this.itemManager.delayedInit();
|
||||
this.reload();
|
||||
this.guiManager.delayedInit();
|
||||
this.recipeManager.delayedInit();
|
||||
this.blockManager.delayedInit();
|
||||
this.itemManager.delayedInit();
|
||||
this.worldManager.delayedInit();
|
||||
this.packManager.delayedInit();
|
||||
this.furnitureManager.delayedInit();
|
||||
|
||||
@@ -5,6 +5,9 @@ import net.momirealms.craftengine.core.plugin.Plugin;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface NetWorkUser {
|
||||
boolean isOnline();
|
||||
|
||||
@@ -16,6 +19,8 @@ public interface NetWorkUser {
|
||||
|
||||
void sendPacket(Object packet, boolean immediately);
|
||||
|
||||
void receivePacket(Object packet);
|
||||
|
||||
@ApiStatus.Internal
|
||||
ConnectionState decoderState();
|
||||
|
||||
@@ -29,4 +34,6 @@ public interface NetWorkUser {
|
||||
Object serverPlayer();
|
||||
|
||||
Object platformPlayer();
|
||||
|
||||
Map<Integer, List<Integer>> furnitureView();
|
||||
}
|
||||
|
||||
@@ -182,6 +182,21 @@ public enum Direction {
|
||||
};
|
||||
}
|
||||
|
||||
public static Direction getApproximateNearest(double x, double y, double z) {
|
||||
Direction nearestDirection = null;
|
||||
double maxDotProduct = -Double.MAX_VALUE;
|
||||
for (Direction direction : Direction.values()) {
|
||||
double dotProduct = x * direction.vec.x() +
|
||||
y * direction.vec.y() +
|
||||
z * direction.vec.z();
|
||||
if (dotProduct > maxDotProduct) {
|
||||
maxDotProduct = dotProduct;
|
||||
nearestDirection = direction;
|
||||
}
|
||||
}
|
||||
return nearestDirection;
|
||||
}
|
||||
|
||||
public static Direction from3DDataValue(int id) {
|
||||
return BY_3D_DATA[Math.abs(id % BY_3D_DATA.length)];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package net.momirealms.craftengine.core.world;
|
||||
|
||||
public enum FluidCollisionRule {
|
||||
NONE,
|
||||
SOURCE_ONLY,
|
||||
ALWAYS
|
||||
}
|
||||
@@ -8,7 +8,9 @@ import java.util.UUID;
|
||||
|
||||
public interface World {
|
||||
|
||||
Object getHandle();
|
||||
Object platformWorld();
|
||||
|
||||
Object serverWorld();
|
||||
|
||||
WorldHeight worldHeight();
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import net.momirealms.craftengine.shared.block.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class CraftEngineBlock extends Block implements BehaviorHolder, ShapeHolder, NoteBlockIndicator, Fallable, BonemealableBlock {
|
||||
private static final PaperWeightStoneBlockShape STONE = new PaperWeightStoneBlockShape(Blocks.STONE.defaultBlockState());
|
||||
private static final StoneBlockShape STONE = new StoneBlockShape(Blocks.STONE.defaultBlockState());
|
||||
private boolean isNoteBlock;
|
||||
public ObjectHolder<BlockBehavior> behaviorHolder;
|
||||
public ObjectHolder<BlockShape> shapeHolder;
|
||||
|
||||
@@ -6,10 +6,10 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.shapes.CollisionContext;
|
||||
import net.momirealms.craftengine.shared.block.BlockShape;
|
||||
|
||||
public class PaperWeightStoneBlockShape implements BlockShape {
|
||||
public class StoneBlockShape implements BlockShape {
|
||||
private final BlockState rawBlockState;
|
||||
|
||||
public PaperWeightStoneBlockShape(BlockState rawBlockState) {
|
||||
public StoneBlockShape(BlockState rawBlockState) {
|
||||
this.rawBlockState = rawBlockState;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ include(":shared")
|
||||
include(":core")
|
||||
include(":bukkit")
|
||||
include(":bukkit:legacy")
|
||||
include(":bukkit:compatibility")
|
||||
include(":bukkit-loader")
|
||||
include(":server-mod")
|
||||
pluginManagement {
|
||||
|
||||
Reference in New Issue
Block a user