9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-27 19:09:08 +00:00

修改家具存储方案

This commit is contained in:
XiaoMoMi
2025-05-11 17:28:11 +08:00
parent b58d5d944c
commit 2d8eb48d51
28 changed files with 360 additions and 64 deletions

View File

@@ -41,7 +41,7 @@ items:
- 0,0,-0.1 0
- 1,0,-0.1 0
loot:
template: "default:loot_table/basic"
template: "default:loot_table/furniture"
arguments:
item: default:bench
default:table_lamp:
@@ -92,7 +92,7 @@ items:
height: 0.4
interactive: true
loot:
template: "default:loot_table/basic"
template: "default:loot_table/furniture"
arguments:
item: default:table_lamp
default:wooden_chair:
@@ -132,6 +132,6 @@ items:
seats:
- 0,0,-0.1 0
loot:
template: "default:loot_table/basic"
template: "default:loot_table/furniture"
arguments:
item: default:wooden_chair

View File

@@ -968,6 +968,18 @@ templates#loot_tables:
- type: item
item: "{item}"
# drop the original furniture item or a fallback item
# template: default:loot_table/furniture
# arguments:
# item: the fallback item
default:loot_table/furniture:
pools:
- rolls: 1
entries:
- type: furniture_item
item: "{item}"
# drop with silk touch
# template: default:loot_table/silk_touch

View File

@@ -9,6 +9,7 @@ import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
import net.momirealms.craftengine.core.entity.furniture.AnchorType;
import net.momirealms.craftengine.core.entity.furniture.CustomFurniture;
import net.momirealms.craftengine.core.entity.furniture.FurnitureExtraData;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.loot.LootTable;
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
@@ -41,7 +42,7 @@ public final class CraftEngineFurniture {
}
/**
* Places furniture at the certain location
* Places furniture at certain location
*
* @param location location
* @param furnitureId furniture to place
@@ -55,7 +56,7 @@ public final class CraftEngineFurniture {
}
/**
* Places furniture at the certain location
* Places furniture at certain location
*
* @param location location
* @param furnitureId furniture to place
@@ -66,11 +67,11 @@ public final class CraftEngineFurniture {
public static LoadedFurniture place(Location location, Key furnitureId, AnchorType anchorType) {
CustomFurniture furniture = byId(furnitureId);
if (furniture == null) return null;
return BukkitFurnitureManager.instance().place(furniture, location, anchorType, true);
return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), true);
}
/**
* Places furniture at the certain location
* Places furniture at certain location
*
* @param location location
* @param furniture furniture to place
@@ -79,11 +80,11 @@ public final class CraftEngineFurniture {
*/
@NotNull
public static LoadedFurniture place(Location location, CustomFurniture furniture, AnchorType anchorType) {
return BukkitFurnitureManager.instance().place(furniture, location, anchorType, true);
return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), true);
}
/**
* Places furniture at the certain location
* Places furniture at certain location
*
* @param location location
* @param furnitureId furniture to place
@@ -95,11 +96,11 @@ public final class CraftEngineFurniture {
public static LoadedFurniture place(Location location, Key furnitureId, AnchorType anchorType, boolean playSound) {
CustomFurniture furniture = byId(furnitureId);
if (furniture == null) return null;
return BukkitFurnitureManager.instance().place(furniture, location, anchorType, playSound);
return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), playSound);
}
/**
* Places furniture at the certain location
* Places furniture at certain location
*
* @param location location
* @param furniture furniture to place
@@ -109,7 +110,7 @@ public final class CraftEngineFurniture {
*/
@NotNull
public static LoadedFurniture place(Location location, CustomFurniture furniture, AnchorType anchorType, boolean playSound) {
return BukkitFurnitureManager.instance().place(furniture, location, anchorType, playSound);
return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), playSound);
}
/**
@@ -222,7 +223,7 @@ public final class CraftEngineFurniture {
}
/**
* Removes furniture by providing a plugin furniture instance
* Removes furniture by providing furniture instance
*
* @param loadedFurniture loaded furniture
* @param dropLoot whether to drop loots
@@ -235,7 +236,7 @@ public final class CraftEngineFurniture {
}
/**
* Removes furniture by providing a plugin furniture instance
* Removes furniture by providing furniture instance
*
* @param loadedFurniture loaded furniture
* @param player the player who removes the furniture
@@ -251,7 +252,7 @@ public final class CraftEngineFurniture {
}
/**
* Removes furniture by providing a plugin furniture instance
* Removes furniture by providing furniture instance
*
* @param loadedFurniture loaded furniture
* @param player the player who removes the furniture
@@ -272,6 +273,7 @@ public final class CraftEngineFurniture {
ContextHolder.Builder builder = ContextHolder.builder();
builder.withParameter(CommonParameters.LOCATION, vec3d);
builder.withParameter(CommonParameters.WORLD, world);
builder.withOptionalParameter(CommonParameters.FURNITURE_ITEM, loadedFurniture.extraData().item().orElse(null));
if (player != null) {
builder.withParameter(CommonParameters.PLAYER, player);
//mark item builder.withOptionalParameter(CommonParameters.MAIN_HAND_ITEM, player.getItemInHand(InteractionHand.MAIN_HAND));

View File

@@ -6,6 +6,7 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.network.handler.FurniturePacketHandler;
import net.momirealms.craftengine.bukkit.util.EntityUtils;
import net.momirealms.craftengine.bukkit.util.LocationUtils;
import net.momirealms.craftengine.bukkit.util.Reflections;
import net.momirealms.craftengine.core.entity.Billboard;
import net.momirealms.craftengine.core.entity.ItemDisplayContext;
@@ -20,7 +21,7 @@ import net.momirealms.craftengine.core.sound.SoundData;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.VersionHelper;
import net.momirealms.craftengine.core.world.Vec3d;
import net.momirealms.craftengine.core.world.WorldPosition;
import org.bukkit.*;
import org.bukkit.entity.*;
import org.bukkit.event.HandlerList;
@@ -31,13 +32,16 @@ import org.jetbrains.annotations.NotNull;
import org.joml.Vector3f;
import javax.annotation.Nullable;
import java.io.IOException;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class BukkitFurnitureManager extends AbstractFurnitureManager {
public static final NamespacedKey FURNITURE_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:furniture_id"));
public static final NamespacedKey FURNITURE_ANCHOR_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:anchor_type"));
// DEPRECATED
// public static final NamespacedKey FURNITURE_ANCHOR_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:anchor_type"));
public static final NamespacedKey FURNITURE_EXTRA_DATA_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:furniture_extra_data"));
public static final NamespacedKey FURNITURE_SEAT_BASE_ENTITY_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:seat_to_base_entity"));
public static final NamespacedKey FURNITURE_SEAT_VECTOR_3F_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:seat_vector"));
public static final NamespacedKey FURNITURE_COLLISION = Objects.requireNonNull(NamespacedKey.fromString("craftengine:collision"));
@@ -66,19 +70,23 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
}
@Override
public Furniture place(CustomFurniture furniture, Vec3d vec3d, net.momirealms.craftengine.core.world.World world, AnchorType anchorType, boolean playSound) {
return this.place(furniture, new Location((World) world.platformWorld(), vec3d.x(), vec3d.y(), vec3d.z()), anchorType, playSound);
public Furniture place(WorldPosition position, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound) {
return this.place(LocationUtils.toLocation(position), furniture, extraData, playSound);
}
public LoadedFurniture place(CustomFurniture furniture, Location location, AnchorType anchorType, boolean playSound) {
if (furniture.isAllowedPlacement(anchorType)) {
anchorType = furniture.getAnyPlacement();
public LoadedFurniture place(Location location, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound) {
Optional<AnchorType> optionalAnchorType = extraData.anchorType();
if (optionalAnchorType.isEmpty() || !furniture.isAllowedPlacement(optionalAnchorType.get())) {
extraData.anchorType(furniture.getAnyPlacement());
}
AnchorType finalAnchorType = anchorType;
Entity furnitureEntity = EntityUtils.spawnEntity(location.getWorld(), location, EntityType.ITEM_DISPLAY, entity -> {
ItemDisplay display = (ItemDisplay) entity;
display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_KEY, PersistentDataType.STRING, furniture.id().toString());
display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_ANCHOR_KEY, PersistentDataType.STRING, finalAnchorType.name());
try {
display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY, extraData.toBytes());
} catch (IOException e) {
this.plugin.logger().warn("Failed to set furniture PDC for " + furniture.id().toString(), e);
}
handleBaseEntityLoadEarly(display);
});
if (playSound) {
@@ -224,9 +232,6 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
handleCollisionEntityLoadOnEntitiesLoad(interaction);
} else if (entity instanceof Boat boat) {
handleCollisionEntityLoadOnEntitiesLoad(boat);
} else if (entity instanceof Shulker shulker) {
// TODO 移除这一行,预计过一个月
handleCollisionEntityLoadOnEntitiesLoad(shulker);
}
}
}
@@ -301,7 +306,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
boolean preventChange = FastNMS.INSTANCE.isPreventingStatusUpdates(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
if (above1_20_1) {
if (!preventChange) {
LoadedFurniture furniture = addNewFurniture(display, customFurniture, getAnchorType(display, customFurniture));
LoadedFurniture furniture = addNewFurniture(display, customFurniture);
furniture.initializeColliders();
for (Player player : display.getTrackedPlayers()) {
this.plugin.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
@@ -309,7 +314,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
}
}
} else {
LoadedFurniture furniture = addNewFurniture(display, customFurniture, getAnchorType(display, customFurniture));
LoadedFurniture furniture = addNewFurniture(display, customFurniture);
for (Player player : display.getTrackedPlayers()) {
this.plugin.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds()));
this.plugin.networkManager().sendPacket(player, furniture.spawnPacket(player));
@@ -373,7 +378,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
CustomFurniture customFurniture = optionalFurniture.get();
LoadedFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId());
if (previous != null) return;
LoadedFurniture furniture = addNewFurniture(display, customFurniture, getAnchorType(display, customFurniture));
LoadedFurniture furniture = addNewFurniture(display, customFurniture);
furniture.initializeColliders(); // safely do it here
}
}
@@ -394,24 +399,37 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager {
collisionEntity.remove();
}
private AnchorType getAnchorType(Entity baseEntity, CustomFurniture furniture) {
String anchorType = baseEntity.getPersistentDataContainer().get(FURNITURE_ANCHOR_KEY, PersistentDataType.STRING);
if (anchorType != null) {
try {
AnchorType unverified = AnchorType.valueOf(anchorType);
if (furniture.isAllowedPlacement(unverified)) {
return unverified;
}
} catch (IllegalArgumentException ignored) {
}
}
AnchorType anchorTypeEnum = furniture.getAnyPlacement();
baseEntity.getPersistentDataContainer().set(FURNITURE_ANCHOR_KEY, PersistentDataType.STRING, anchorTypeEnum.name());
return anchorTypeEnum;
private FurnitureExtraData getFurnitureExtraData(Entity baseEntity) throws IOException {
byte[] extraData = baseEntity.getPersistentDataContainer().get(FURNITURE_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY);
if (extraData == null) return FurnitureExtraData.builder().build();
return FurnitureExtraData.fromBytes(extraData);
}
private synchronized LoadedFurniture addNewFurniture(ItemDisplay display, CustomFurniture furniture, AnchorType anchorType) {
LoadedFurniture loadedFurniture = new LoadedFurniture(display, furniture, anchorType);
// private AnchorType getAnchorType(Entity baseEntity, CustomFurniture furniture) {
// String anchorType = baseEntity.getPersistentDataContainer().get(FURNITURE_ANCHOR_KEY, PersistentDataType.STRING);
// if (anchorType != null) {
// try {
// AnchorType unverified = AnchorType.valueOf(anchorType);
// if (furniture.isAllowedPlacement(unverified)) {
// return unverified;
// }
// } catch (IllegalArgumentException ignored) {
// }
// }
// AnchorType anchorTypeEnum = furniture.getAnyPlacement();
// baseEntity.getPersistentDataContainer().set(FURNITURE_ANCHOR_KEY, PersistentDataType.STRING, anchorTypeEnum.name());
// return anchorTypeEnum;
// }
private synchronized LoadedFurniture addNewFurniture(ItemDisplay display, CustomFurniture furniture) {
FurnitureExtraData extraData;
try {
extraData = getFurnitureExtraData(display);
} catch (IOException e) {
extraData = FurnitureExtraData.builder().build();
plugin.logger().warn("Furniture extra data could not be loaded", e);
}
LoadedFurniture loadedFurniture = new LoadedFurniture(display, furniture, extraData);
this.furnitureByRealEntityId.put(loadedFurniture.baseEntityId(), loadedFurniture);
for (int entityId : loadedFurniture.entityIds()) {
this.furnitureByEntityId.put(entityId, loadedFurniture);

View File

@@ -31,6 +31,7 @@ public class LoadedFurniture implements Furniture {
private final Key id;
private final CustomFurniture furniture;
private final AnchorType anchorType;
private final FurnitureExtraData extraData;
// location
private final Location location;
// base entity
@@ -54,10 +55,11 @@ public class LoadedFurniture implements Furniture {
public LoadedFurniture(Entity baseEntity,
CustomFurniture furniture,
AnchorType anchorType) {
FurnitureExtraData extraData) {
this.id = furniture.id();
this.extraData = extraData;
this.baseEntityId = baseEntity.getEntityId();
this.anchorType = anchorType;
this.anchorType = extraData.anchorType().orElse(furniture.getAnyPlacement());
this.location = baseEntity.getLocation();
this.baseEntity = new WeakReference<>(baseEntity);
this.furniture = furniture;
@@ -305,6 +307,11 @@ public class LoadedFurniture implements Furniture {
spawnSeatEntityForPlayer((Player) player.platformPlayer(), seat);
}
@Override
public FurnitureExtraData extraData() {
return this.extraData;
}
public void spawnSeatEntityForPlayer(org.bukkit.entity.Player player, Seat seat) {
Location location = this.calculateSeatLocation(seat);
Entity seatEntity = seat.limitPlayerRotation() ?

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.bukkit.item;
import com.saicone.rtag.item.ItemTagStream;
import net.momirealms.craftengine.bukkit.item.behavior.AxeItemBehavior;
import net.momirealms.craftengine.bukkit.item.behavior.BoneMealItemBehavior;
import net.momirealms.craftengine.bukkit.item.behavior.BucketItemBehavior;
@@ -163,6 +164,11 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
HandlerList.unregisterAll(this.debugStickListener);
}
@Override
public Item<ItemStack> fromByteArray(byte[] bytes) {
return this.factory.wrap(ItemTagStream.INSTANCE.fromBytes(bytes));
}
@Override
public ConfigParser parser() {
return this.itemParser;

View File

@@ -71,7 +71,7 @@ public class ComponentItemWrapper implements ItemWrapper<ItemStack> {
@Override
public ItemWrapper<ItemStack> copyWithCount(int count) {
ItemStack copied = item.clone();
ItemStack copied = this.item.clone();
copied.setAmount(count);
return new ComponentItemWrapper(copied);
}

View File

@@ -25,6 +25,7 @@ public class ComponentTypes {
public static final Object REPAIR_COST = getComponentType(ComponentKeys.REPAIR_COST);
public static final Object CUSTOM_DATA = getComponentType(ComponentKeys.CUSTOM_DATA);
public static final Object PROFILE = getComponentType(ComponentKeys.PROFILE);
public static final Object DYED_COLOR = getComponentType(ComponentKeys.DYED_COLOR);
private ComponentTypes() {}

View File

@@ -10,6 +10,7 @@ import net.momirealms.craftengine.bukkit.util.DirectionUtils;
import net.momirealms.craftengine.bukkit.util.EventUtils;
import net.momirealms.craftengine.core.entity.furniture.AnchorType;
import net.momirealms.craftengine.core.entity.furniture.CustomFurniture;
import net.momirealms.craftengine.core.entity.furniture.FurnitureExtraData;
import net.momirealms.craftengine.core.entity.furniture.HitBox;
import net.momirealms.craftengine.core.entity.player.InteractionResult;
import net.momirealms.craftengine.core.entity.player.Player;
@@ -126,7 +127,15 @@ public class FurnitureItemBehavior extends ItemBehavior {
return InteractionResult.FAIL;
}
LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().place(customFurniture, furnitureLocation.clone(), anchorType, false);
Item<?> item = context.getItem();
LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().place(
furnitureLocation.clone(), customFurniture,
FurnitureExtraData.builder()
.item(item.copyWithCount(1))
.anchorType(anchorType)
.dyedColor(item.dyedColor().orElse(-1))
.build(), false);
FurniturePlaceEvent placeEvent = new FurniturePlaceEvent(bukkitPlayer, loadedFurniture, furnitureLocation, context.getHand());
if (EventUtils.fireAndCheckCancel(placeEvent)) {
@@ -135,7 +144,6 @@ public class FurnitureItemBehavior extends ItemBehavior {
}
if (!player.isCreativeMode()) {
Item<?> item = context.getItem();
item.count(item.count() - 1);
item.load();
}

View File

@@ -1,6 +1,7 @@
package net.momirealms.craftengine.bukkit.item.factory;
import com.google.gson.JsonElement;
import com.saicone.rtag.item.ItemTagStream;
import net.momirealms.craftengine.bukkit.util.ItemTags;
import net.momirealms.craftengine.bukkit.util.Reflections;
import net.momirealms.craftengine.core.item.EquipmentData;
@@ -46,6 +47,11 @@ public abstract class BukkitItemFactory<W extends ItemWrapper<ItemStack>> extend
}
}
@Override
protected byte[] toByteArray(W item) {
return ItemTagStream.INSTANCE.toBytes(item.getItem());
}
@Override
protected boolean isBlockItem(W item) {
return item.getItem().getType().isBlock();

View File

@@ -244,6 +244,26 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
}
}
@Override
protected Optional<Integer> dyedColor(ComponentItemWrapper item) {
if (!item.hasComponent(ComponentTypes.DYED_COLOR)) return Optional.empty();
return Optional.ofNullable(
(Integer) ComponentType.encodeJava(
ComponentTypes.DYED_COLOR,
item.getComponent(ComponentTypes.DYED_COLOR)
).orElse(null)
);
}
@Override
protected void dyedColor(ComponentItemWrapper item, Integer color) {
if (color == null) {
item.resetComponent(ComponentTypes.DYED_COLOR);
} else {
item.setJavaComponent(ComponentTypes.DYED_COLOR, color);
}
}
@Override
protected Optional<Integer> maxDamage(ComponentItemWrapper item) {
if (!item.hasComponent(ComponentTypes.MAX_DAMAGE)) return Optional.of((int) item.getItem().getType().getMaxDurability());

View File

@@ -152,6 +152,21 @@ public class UniversalItemFactory extends BukkitItemFactory<LegacyItemWrapper> {
item.set(damage, "Damage");
}
@Override
protected Optional<Integer> dyedColor(LegacyItemWrapper item) {
if (!item.hasTag("display", "color")) return Optional.empty();
return Optional.of(item.get("display", "color"));
}
@Override
protected void dyedColor(LegacyItemWrapper item, Integer color) {
if (color == null) {
item.remove("display", "color");
} else {
item.set(color, "display", "color");
}
}
@Override
protected Optional<Integer> maxDamage(LegacyItemWrapper item) {
return Optional.of((int) item.getItem().getType().getMaxDurability());

View File

@@ -1,5 +1,6 @@
package net.momirealms.craftengine.bukkit.plugin.command.feature;
import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture;
import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager;
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
import net.momirealms.craftengine.bukkit.util.KeyUtils;
@@ -55,7 +56,7 @@ public class DebugSpawnFurnitureCommand extends BukkitCommandFeature<CommandSend
CustomFurniture customFurniture = optionalCustomFurniture.get();
AnchorType anchorType = (AnchorType) context.optional("anchor-type").orElse(customFurniture.getAnyPlacement());
boolean playSound = context.flags().hasFlag("silent");
furnitureManager.place(customFurniture, location, anchorType, !playSound);
CraftEngineFurniture.place(location, customFurniture, anchorType, playSound);
});
}

View File

@@ -1,31 +1,25 @@
package net.momirealms.craftengine.bukkit.plugin.command.feature;
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature;
import net.momirealms.craftengine.bukkit.util.BlockTags;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager;
import net.momirealms.craftengine.core.util.Key;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.Command;
import org.incendo.cloud.bukkit.data.BlockPredicate;
import org.incendo.cloud.bukkit.parser.BlockPredicateParser;
import org.incendo.cloud.bukkit.parser.NamespacedKeyParser;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.context.CommandInput;
import org.incendo.cloud.parser.standard.BooleanParser;
import org.incendo.cloud.parser.standard.ByteParser;
import org.incendo.cloud.parser.standard.StringParser;
import org.incendo.cloud.suggestion.Suggestion;
import org.incendo.cloud.suggestion.SuggestionProvider;
import java.util.*;
import java.util.Collection;
import java.util.HashSet;
import java.util.concurrent.CompletableFuture;
public class TestCommand extends BukkitCommandFeature<CommandSender> {

View File

@@ -3,13 +3,19 @@ package net.momirealms.craftengine.bukkit.util;
import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.core.world.BlockPos;
import net.momirealms.craftengine.core.world.Vec3d;
import net.momirealms.craftengine.core.world.WorldPosition;
import org.bukkit.Location;
import org.bukkit.World;
import org.jetbrains.annotations.NotNull;
public class LocationUtils {
private LocationUtils() {}
public static Location toLocation(WorldPosition position) {
return new Location((World) position.world().platformWorld(), position.position().x(), position.position().y(), position.position().z());
}
public static Vec3d toVec3d(Location loc) {
return new Vec3d(loc.getX(), loc.getY(), loc.getZ());
}

View File

@@ -46,4 +46,6 @@ public interface Furniture {
boolean hasExternalModel();
void spawnSeatEntityForPlayer(Player player, Seat seat);
FurnitureExtraData extraData();
}

View File

@@ -0,0 +1,86 @@
package net.momirealms.craftengine.core.entity.furniture;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.sparrow.nbt.CompoundTag;
import net.momirealms.sparrow.nbt.NBT;
import java.io.IOException;
import java.util.Optional;
public class FurnitureExtraData {
public static final String ITEM = "item";
public static final String DYED_COLOR = "dyed_color";
public static final String ANCHOR_TYPE = "anchor_type";
private final CompoundTag data;
public FurnitureExtraData(CompoundTag data) {
this.data = data;
}
public Optional<Item<?>> item() {
byte[] data = this.data.getByteArray(ITEM);
if (data == null) return Optional.empty();
return Optional.of(CraftEngine.instance().itemManager().fromByteArray(data));
}
public Optional<Integer> dyedColor() {
if (this.data.containsKey(DYED_COLOR)) return Optional.of(this.data.getInt(DYED_COLOR));
return Optional.empty();
}
public Optional<AnchorType> anchorType() {
if (this.data.containsKey(ANCHOR_TYPE)) return Optional.of(AnchorType.byId(this.data.getInt(ANCHOR_TYPE)));
return Optional.empty();
}
public FurnitureExtraData anchorType(AnchorType type) {
this.data.putInt(ANCHOR_TYPE, type.getId());
return this;
}
public static Builder builder() {
return new Builder();
}
public static FurnitureExtraData fromBytes(final byte[] data) throws IOException {
return new FurnitureExtraData(NBT.fromBytes(data));
}
public static byte[] toBytes(final FurnitureExtraData data) throws IOException {
return NBT.toBytes(data.data);
}
public byte[] toBytes() throws IOException {
return toBytes(this);
}
public static class Builder {
private final CompoundTag data;
public Builder() {
this.data = new CompoundTag();
}
public Builder item(Item<?> item) {
this.data.putByteArray(ITEM, item.toByteArray());
return this;
}
public Builder dyedColor(int color) {
if (color < 0) return this;
this.data.putInt(DYED_COLOR, color);
return this;
}
public Builder anchorType(AnchorType type) {
this.data.putInt(ANCHOR_TYPE, type.getId());
return this;
}
public FurnitureExtraData build() {
return new FurnitureExtraData(data);
}
}
}

View File

@@ -4,8 +4,7 @@ import net.momirealms.craftengine.core.entity.AbstractEntity;
import net.momirealms.craftengine.core.plugin.Manageable;
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.world.Vec3d;
import net.momirealms.craftengine.core.world.World;
import net.momirealms.craftengine.core.world.WorldPosition;
import org.incendo.cloud.suggestion.Suggestion;
import javax.annotation.Nullable;
@@ -21,7 +20,7 @@ public interface FurnitureManager extends Manageable {
Collection<Suggestion> cachedSuggestions();
Furniture place(CustomFurniture furniture, Vec3d vec3d, World world, AnchorType anchorType, boolean playSound);
Furniture place(WorldPosition position, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound);
Optional<CustomFurniture> furnitureById(Key id);

View File

@@ -93,6 +93,17 @@ public class AbstractItem<W extends ItemWrapper<I>, I> implements Item<I> {
return this.factory.maxDamage(this.item);
}
@Override
public Item<I> dyedColor(Integer data) {
this.factory.dyedColor(this.item, data);
return this;
}
@Override
public Optional<Integer> dyedColor() {
return this.factory.dyedColor(this.item);
}
@SuppressWarnings("unchecked")
@Override
public Optional<CustomItem<I>> getCustomItem() {
@@ -358,4 +369,9 @@ public class AbstractItem<W extends ItemWrapper<I>, I> implements Item<I> {
public void merge(Item<I> another) {
this.factory.merge(this.item, (W) ((AbstractItem) another).item);
}
@Override
public byte[] toByteArray() {
return this.factory.toByteArray(this.item);
}
}

View File

@@ -22,4 +22,5 @@ public class ComponentKeys {
public static final Key REPAIR_COST = Key.of("minecraft", "repair_cost");
public static final Key CUSTOM_DATA = Key.of("minecraft", "custom_data");
public static final Key PROFILE = Key.of("minecraft", "profile");
public static final Key DYED_COLOR = Key.of("minecraft", "dyed_color");
}

View File

@@ -56,6 +56,10 @@ public interface Item<I> {
Optional<Integer> maxDamage();
Item<I> dyedColor(Integer data);
Optional<Integer> dyedColor();
Item<I> customName(String displayName);
Optional<String> customName();
@@ -145,4 +149,6 @@ public interface Item<I> {
Item<I> mergeCopy(Item<?> another);
void merge(Item<I> another);
byte[] toByteArray();
}

View File

@@ -83,6 +83,10 @@ public abstract class ItemFactory<W extends ItemWrapper<I>, I> {
protected abstract void damage(W item, Integer damage);
protected abstract Optional<Integer> dyedColor(W item);
protected abstract void dyedColor(W item, Integer color);
protected abstract Optional<Integer> maxDamage(W item);
protected abstract void maxDamage(W item, Integer damage);
@@ -138,4 +142,7 @@ public abstract class ItemFactory<W extends ItemWrapper<I>, I> {
protected abstract void equippable(W item, EquipmentData data);
protected abstract Optional<EquipmentData> equippable(W item);
protected abstract byte[] toByteArray(W item);
}

View File

@@ -41,6 +41,8 @@ public interface ItemManager<T> extends Manageable, ModelGenerator {
Item<T> wrap(T itemStack);
Item<T> fromByteArray(byte[] bytes);
Collection<Key> items();
Key itemId(T itemStack);

View File

@@ -0,0 +1,58 @@
package net.momirealms.craftengine.core.loot.entry;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.loot.LootConditions;
import net.momirealms.craftengine.core.loot.LootContext;
import net.momirealms.craftengine.core.loot.function.LootFunction;
import net.momirealms.craftengine.core.loot.function.LootFunctions;
import net.momirealms.craftengine.core.plugin.context.Condition;
import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.Consumer;
public class FurnitureItemLootEntryContainer<T> extends SingleItemLootEntryContainer<T> {
public static final Factory<?> FACTORY = new Factory<>();
private final boolean hasFallback;
protected FurnitureItemLootEntryContainer(@Nullable Key item, List<Condition<LootContext>> conditions, List<LootFunction<T>> lootFunctions, int weight, int quality) {
super(item, conditions, lootFunctions, weight, quality);
this.hasFallback = item != null;
}
@Override
public Key type() {
return LootEntryContainers.FURNITURE_ITEM;
}
@SuppressWarnings("unchecked")
@Override
protected void createItem(Consumer<Item<T>> lootConsumer, LootContext context) {
Optional<Item<?>> optionalItem = context.getOptionalParameter(CommonParameters.FURNITURE_ITEM);
if (optionalItem.isPresent()) {
lootConsumer.accept((Item<T>) optionalItem.get());
} else if (this.hasFallback) {
super.createItem(lootConsumer, context);
}
}
public static class Factory<A> implements LootEntryContainerFactory<A> {
@SuppressWarnings("unchecked")
@Override
public LootEntryContainer<A> create(Map<String, Object> arguments) {
Key item = Optional.ofNullable(arguments.get("item")).map(String::valueOf).map(Key::of).orElse(null);
int weight = ResourceConfigUtils.getAsInt(arguments.getOrDefault("weight", 1), "weight");
int quality = ResourceConfigUtils.getAsInt(arguments.getOrDefault("quality", 0), "quality");
List<Condition<LootContext>> conditions = Optional.ofNullable(arguments.get("conditions"))
.map(it -> LootConditions.fromMapList((List<Map<String, Object>>) it))
.orElse(Collections.emptyList());
List<LootFunction<A>> functions = Optional.ofNullable(arguments.get("functions"))
.map(it -> (List<LootFunction<A>>) new ArrayList<LootFunction<A>>(LootFunctions.fromMapList((List<Map<String, Object>>) it)))
.orElse(Collections.emptyList());
return new FurnitureItemLootEntryContainer<>(item, conditions, functions, weight, quality);
}
}
}

View File

@@ -16,12 +16,14 @@ import java.util.Map;
public class LootEntryContainers {
public static final Key ALTERNATIVES = Key.from("craftengine:alternatives");
public static final Key ITEM = Key.from("craftengine:item");
public static final Key FURNITURE_ITEM = Key.from("craftengine:furniture_item");
public static final Key EXP = Key.from("craftengine:exp");
static {
register(ALTERNATIVES, AlternativesLootEntryContainer.FACTORY);
register(ITEM, SingleItemLootEntryContainer.FACTORY);
register(EXP, ExpLootEntryContainer.FACTORY);
register(FURNITURE_ITEM, FurnitureItemLootEntryContainer.FACTORY);
}
public static <T> void register(Key key, LootEntryContainerFactory<T> factory) {

View File

@@ -2,6 +2,7 @@ package net.momirealms.craftengine.core.plugin.context.parameter;
import net.momirealms.craftengine.core.block.ImmutableBlockState;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.plugin.context.ContextKey;
import net.momirealms.craftengine.core.world.Vec3d;
import net.momirealms.craftengine.core.world.World;
@@ -13,6 +14,7 @@ public final class CommonParameters {
public static final ContextKey<Double> LAST_RANDOM = ContextKey.of("last_random");
public static final ContextKey<Vec3d> LOCATION = ContextKey.of("location");
public static final ContextKey<World> WORLD = ContextKey.of("world");
public static final ContextKey<Item<?>> FURNITURE_ITEM = ContextKey.of("furniture_item");
public static final ContextKey<Boolean> FALLING_BLOCK = ContextKey.of("falling_block");
public static final ContextKey<Float> EXPLOSION_RADIUS = ContextKey.of("explosion_radius");
public static final ContextKey<Player> PLAYER = ContextKey.of("player");

View File

@@ -0,0 +1,19 @@
package net.momirealms.craftengine.core.world;
public class WorldPosition {
private final World world;
private final Position position;
public WorldPosition(Position position, World world) {
this.position = position;
this.world = world;
}
public Position position() {
return position;
}
public World world() {
return world;
}
}

View File

@@ -21,7 +21,7 @@ asm_version=9.8
asm_commons_version=9.8
jar_relocator_version=1.7
adventure_bundle_version=4.21.0
adventure_platform_version=4.3.4
adventure_platform_version=4.4.0
cloud_core_version=2.0.0
cloud_services_version=2.0.0
cloud_brigadier_version=2.0.0-beta.10