Add the player-use peripheral for CC:Tweaked #9
35
src/main/java/net/banutama/utamacraft/CCRegistration.java
Normal file
35
src/main/java/net/banutama/utamacraft/CCRegistration.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package net.banutama.utamacraft;
|
||||||
|
|
||||||
|
import com.mojang.logging.LogUtils;
|
||||||
|
import dan200.computercraft.api.ForgeComputerCraftAPI;
|
||||||
|
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||||
|
import net.banutama.utamacraft.integrations.computercraft.PeripheralProvider;
|
||||||
|
import net.banutama.utamacraft.integrations.computercraft.turtles.TurtlePlayerUpgrade;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraftforge.eventbus.api.IEventBus;
|
||||||
|
import net.minecraftforge.registries.DeferredRegister;
|
||||||
|
import net.minecraftforge.registries.RegistryObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CC:Tweaked registration
|
||||||
|
*/
|
||||||
|
public class CCRegistration {
|
||||||
|
|
||||||
|
public static final DeferredRegister<TurtleUpgradeSerialiser<?>> TURTLE_SERIALIZERS =
|
||||||
|
DeferredRegister.create(TurtleUpgradeSerialiser.REGISTRY_ID, Utamacraft.MOD_ID);
|
||||||
|
|
||||||
|
public static final RegistryObject<TurtleUpgradeSerialiser<TurtlePlayerUpgrade>> PLAYER_TURTLE =
|
||||||
|
TURTLE_SERIALIZERS.register(ID.PLAYER_TURTLE.getPath(), () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtlePlayerUpgrade::new));
|
||||||
|
|
||||||
|
public static PeripheralProvider peripheralProvider = new PeripheralProvider();
|
||||||
|
|
||||||
|
public static void register(IEventBus bus) {
|
||||||
|
TURTLE_SERIALIZERS.register(bus);
|
||||||
|
ForgeComputerCraftAPI.registerPeripheralProvider(peripheralProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ID {
|
||||||
|
public static final ResourceLocation PLAYER_TURTLE = new ResourceLocation(Utamacraft.MOD_ID, "player_turtle");
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,7 @@ public class Utamacraft {
|
|||||||
|
|
||||||
ModItems.register(bus);
|
ModItems.register(bus);
|
||||||
ModBlocks.register(bus);
|
ModBlocks.register(bus);
|
||||||
|
CCRegistration.register(bus);
|
||||||
|
|
||||||
bus.addListener(this::commonSetup);
|
bus.addListener(this::commonSetup);
|
||||||
MinecraftForge.EVENT_BUS.register(this);
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
@ -37,7 +38,7 @@ public class Utamacraft {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Mod.EventBusSubscriber(modid = MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
|
@Mod.EventBusSubscriber(modid = MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
|
||||||
public static class ClientModEvents {
|
public static class ModEvents {
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onClientSetup(FMLClientSetupEvent event) {
|
public static void onClientSetup(FMLClientSetupEvent event) {
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package net.banutama.utamacraft.client;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.client.ComputerCraftAPIClient;
|
||||||
|
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||||
|
import net.banutama.utamacraft.CCRegistration;
|
||||||
|
import net.banutama.utamacraft.Utamacraft;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||||
|
|
||||||
|
@Mod.EventBusSubscriber(modid = Utamacraft.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
|
||||||
|
public class ClientRegistry {
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onClientSetup(FMLClientSetupEvent event) {
|
||||||
|
ComputerCraftAPIClient.registerTurtleUpgradeModeller(CCRegistration.PLAYER_TURTLE.get(), TurtleUpgradeModeller.flatItem());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package net.banutama.utamacraft.integrations.computercraft;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.*;
|
||||||
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
|
import dan200.computercraft.core.asm.NamedMethod;
|
||||||
|
import dan200.computercraft.core.asm.PeripheralMethod;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class BoundMethod {
|
||||||
|
private final Object target;
|
||||||
|
private final String name;
|
||||||
|
private final PeripheralMethod method;
|
||||||
|
|
||||||
|
public BoundMethod(@NotNull Object target, @NotNull NamedMethod<PeripheralMethod> method) {
|
||||||
|
this.target = target;
|
||||||
|
this.name = method.getName();
|
||||||
|
this.method = method.getMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public MethodResult apply(@NotNull IComputerAccess computer, @NotNull ILuaContext context, @NotNull IArguments arguments) throws LuaException {
|
||||||
|
return method.apply(target, context, computer, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
if (this == other) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(other instanceof BoundMethod boundMethod)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return target.equals(boundMethod.target) && name.equals(boundMethod.name) && method.equals(boundMethod.method);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(target, name, method);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package net.banutama.utamacraft.integrations.computercraft;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheralProvider;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class PeripheralProvider implements IPeripheralProvider {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public LazyOptional<IPeripheral> getPeripheral(@NotNull Level world, @NotNull BlockPos pos, @NotNull Direction side) {
|
||||||
|
return LazyOptional.empty();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package net.banutama.utamacraft.integrations.computercraft.peripheral;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.IArguments;
|
||||||
|
import dan200.computercraft.api.lua.ILuaContext;
|
||||||
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
|
import dan200.computercraft.api.lua.MethodResult;
|
||||||
|
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||||
|
import dan200.computercraft.api.peripheral.IDynamicPeripheral;
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
|
import dan200.computercraft.core.asm.PeripheralMethod;
|
||||||
|
import net.banutama.utamacraft.integrations.computercraft.BoundMethod;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public abstract class BasePeripheral implements IPeripheral, IDynamicPeripheral {
|
||||||
|
protected final String type;
|
||||||
|
protected final BasePeripheralOwner owner;
|
||||||
|
protected final List<BoundMethod> methods;
|
||||||
|
protected final Set<IComputerAccess> computers = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||||
|
|
||||||
|
protected BasePeripheral(String type, BasePeripheralOwner owner) {
|
||||||
|
this.type = type;
|
||||||
|
this.owner = owner;
|
||||||
|
this.methods = PeripheralMethod.GENERATOR.getMethods(this.getClass()).stream().map(named -> new BoundMethod(this, named)).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String @NotNull [] getMethodNames() {
|
||||||
|
return methods.stream().map(BoundMethod::getName).toArray(String[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public MethodResult callMethod(@NotNull IComputerAccess computer, @NotNull ILuaContext context, int method, @NotNull IArguments arguments) throws LuaException {
|
||||||
|
return methods.get(method).apply(computer, context, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attach(@NotNull IComputerAccess computer) {
|
||||||
|
this.computers.add(computer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void detach(@NotNull IComputerAccess computer) {
|
||||||
|
this.computers.remove(computer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Object getTarget() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable IPeripheral other) {
|
||||||
|
return Objects.equals(this, other);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package net.banutama.utamacraft.integrations.computercraft.peripheral;
|
||||||
|
|
||||||
|
public class BasePeripheralOwner {
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package net.banutama.utamacraft.integrations.computercraft.peripheral;
|
||||||
|
|
||||||
|
public class BlockEntityPeripheralOwner extends BasePeripheralOwner {
|
||||||
|
// TODO: After we add PeripheralBlockEntity we want to add it to a field and constructor here.
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package net.banutama.utamacraft.integrations.computercraft.peripheral;
|
||||||
|
|
||||||
|
import com.mojang.logging.LogUtils;
|
||||||
|
import dan200.computercraft.api.lua.LuaFunction;
|
||||||
|
import dan200.computercraft.api.lua.MethodResult;
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
|
import net.banutama.utamacraft.integrations.computercraft.turtles.TurtlePlayerCache;
|
||||||
|
import net.minecraft.world.InteractionResult;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
public class PlayerPeripheral extends BasePeripheral {
|
||||||
|
public static final String PERIPHERAL_TYPE = "player";
|
||||||
|
private static final Logger LOGGER = LogUtils.getLogger();
|
||||||
|
|
||||||
|
protected PlayerPeripheral(BasePeripheralOwner owner) {
|
||||||
|
super(PERIPHERAL_TYPE, owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerPeripheral(ITurtleAccess turtle, TurtleSide side) {
|
||||||
|
this(new TurtlePeripheralOwner(turtle, side));
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction(mainThread = true)
|
||||||
|
public final MethodResult use() {
|
||||||
|
if (!(owner instanceof TurtlePeripheralOwner turtleOwner)) {
|
||||||
|
LOGGER.info("Owner of this PlayerPeripheral is not a TurtlePeripheralOwner");
|
||||||
|
return MethodResult.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
InteractionResult result = TurtlePlayerCache.withPlayer(turtleOwner.getTurtle(),
|
||||||
|
player -> player.use(5, true, false, null));
|
||||||
|
|
||||||
|
return MethodResult.of(result.name());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package net.banutama.utamacraft.integrations.computercraft.peripheral;
|
||||||
|
|
||||||
|
public class PocketPeripheralOwner extends BasePeripheralOwner {
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package net.banutama.utamacraft.integrations.computercraft.peripheral;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
|
|
||||||
|
public class TurtlePeripheralOwner extends BasePeripheralOwner {
|
||||||
|
private final ITurtleAccess turtle;
|
||||||
|
private final TurtleSide side;
|
||||||
|
|
||||||
|
public TurtlePeripheralOwner(ITurtleAccess turtle, TurtleSide side) {
|
||||||
|
this.turtle = turtle;
|
||||||
|
this.side = side;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITurtleAccess getTurtle() {
|
||||||
|
return turtle;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package net.banutama.utamacraft.integrations.computercraft.turtles;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
|
import dan200.computercraft.api.turtle.AbstractTurtleUpgrade;
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
|
import dan200.computercraft.api.turtle.TurtleUpgradeType;
|
||||||
|
import net.banutama.utamacraft.integrations.computercraft.peripheral.BasePeripheral;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public abstract class PeripheralTurtleUpgrade<T extends BasePeripheral> extends AbstractTurtleUpgrade {
|
||||||
|
|
||||||
|
protected PeripheralTurtleUpgrade(ResourceLocation id, ItemStack item) {
|
||||||
|
super(id, TurtleUpgradeType.PERIPHERAL, String.format("turtle.utamacraft.%s", id.getPath()), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract T buildPeripheral(@NotNull ITurtleAccess turtle, @NotNull TurtleSide side);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public IPeripheral createPeripheral(@NotNull ITurtleAccess turtle, @NotNull TurtleSide side) {
|
||||||
|
return buildPeripheral(turtle, side);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package net.banutama.utamacraft.integrations.computercraft.turtles;
|
||||||
|
|
||||||
|
import com.mojang.authlib.GameProfile;
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
|
import net.banutama.utamacraft.util.FakeGameProfile;
|
||||||
|
import net.banutama.utamacraft.util.SimpleFakePlayer;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.core.Vec3i;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class TurtlePlayerCache {
|
||||||
|
private static final WeakHashMap<ITurtleAccess, SimpleFakePlayer> PLAYERS = new WeakHashMap<>();
|
||||||
|
|
||||||
|
private static SimpleFakePlayer getPlayerFor(ITurtleAccess turtle, GameProfile profile) {
|
||||||
|
SimpleFakePlayer player = PLAYERS.get(turtle);
|
||||||
|
if (player == null) {
|
||||||
|
player = new SimpleFakePlayer((ServerLevel)turtle.getLevel(), profile);
|
||||||
|
PLAYERS.put(turtle, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T withPlayer(ITurtleAccess turtle, Function<SimpleFakePlayer, T> callback) {
|
||||||
|
GameProfile profile = turtle.getOwningPlayer();
|
||||||
|
if (profile == null) {
|
||||||
|
profile = new FakeGameProfile();
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleFakePlayer player = getPlayerFor(turtle, profile);
|
||||||
|
BlockPos position = turtle.getPosition();
|
||||||
|
Direction direction = turtle.getDirection();
|
||||||
|
|
||||||
|
float pitch = direction == Direction.UP ? -90.0f : direction == Direction.DOWN ? 90.0f : 0.0f;
|
||||||
|
float yaw = direction == Direction.SOUTH ? 0.0f : direction == Direction.WEST ? 90.0f : direction == Direction.NORTH ? 180.0f : -90.0f;
|
||||||
|
|
||||||
|
Vec3i normal = direction.getNormal();
|
||||||
|
Direction.Axis axis = direction.getAxis();
|
||||||
|
Direction.AxisDirection axis_dir = direction.getAxisDirection();
|
||||||
|
|
||||||
|
double x = (axis == Direction.Axis.X && axis_dir == Direction.AxisDirection.NEGATIVE) ? -0.5 : (0.5 * normal.getX() / 1.9);
|
||||||
|
double y = 0.5 + normal.getY() / 1.9;
|
||||||
|
double z = (axis == Direction.Axis.Z && axis_dir == Direction.AxisDirection.NEGATIVE) ? -0.5 : (0.5 + normal.getZ() / 1.9);
|
||||||
|
|
||||||
|
player.moveTo(position.getX() + x, position.getY() + y, position.getZ() + z, yaw, pitch);
|
||||||
|
return callback.apply(player);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package net.banutama.utamacraft.integrations.computercraft.turtles;
|
||||||
|
|
||||||
|
import com.mojang.logging.LogUtils;
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||||
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
|
import net.banutama.utamacraft.integrations.computercraft.peripheral.PlayerPeripheral;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
public class TurtlePlayerUpgrade extends PeripheralTurtleUpgrade<PlayerPeripheral> {
|
||||||
|
private static final Logger LOGGER = LogUtils.getLogger();
|
||||||
|
|
||||||
|
public TurtlePlayerUpgrade(ResourceLocation id, ItemStack item) {
|
||||||
|
super(id, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PlayerPeripheral buildPeripheral(@NotNull ITurtleAccess turtle, @NotNull TurtleSide side) {
|
||||||
|
LOGGER.info("Building PlayerPeripheral for TurtlePlayerUpgrade");
|
||||||
|
return new PlayerPeripheral(turtle, side);
|
||||||
|
}
|
||||||
|
}
|
10
src/main/java/net/banutama/utamacraft/item/BaseItem.java
Normal file
10
src/main/java/net/banutama/utamacraft/item/BaseItem.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package net.banutama.utamacraft.item;
|
||||||
|
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public abstract class BaseItem extends Item {
|
||||||
|
public BaseItem(@NotNull Properties properties) {
|
||||||
|
super(properties.tab(ModCreativeModeTab.TAB));
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,6 @@ package net.banutama.utamacraft.item;
|
|||||||
import net.banutama.utamacraft.Utamacraft;
|
import net.banutama.utamacraft.Utamacraft;
|
||||||
import net.minecraft.world.item.CreativeModeTab;
|
import net.minecraft.world.item.CreativeModeTab;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -11,7 +10,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
public class ModCreativeModeTab {
|
public class ModCreativeModeTab {
|
||||||
public static final CreativeModeTab TAB = new CreativeModeTab("utamacraft_tab") {
|
public static final CreativeModeTab TAB = new CreativeModeTab("utamacraft_tab") {
|
||||||
@Override
|
@Override
|
||||||
public ItemStack makeIcon() {
|
public @NotNull ItemStack makeIcon() {
|
||||||
return new ItemStack(ModItems.LOGO.get());
|
return new ItemStack(ModItems.LOGO.get());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -11,8 +11,11 @@ public class ModItems {
|
|||||||
public static final DeferredRegister<Item> ITEMS =
|
public static final DeferredRegister<Item> ITEMS =
|
||||||
DeferredRegister.create(ForgeRegistries.ITEMS, Utamacraft.MOD_ID);
|
DeferredRegister.create(ForgeRegistries.ITEMS, Utamacraft.MOD_ID);
|
||||||
|
|
||||||
public static final RegistryObject<Item> LOGO = ITEMS.register("utamacraft_logo",
|
public static final RegistryObject<Item> LOGO =
|
||||||
() -> new Item(new Item.Properties()));
|
ITEMS.register("utamacraft_logo", () -> new Item(new Item.Properties()));
|
||||||
|
|
||||||
|
public static final RegistryObject<Item> PLAYER_PERIPHERAL =
|
||||||
|
ITEMS.register("player_peripheral", PlayerPeripheralItem::new);
|
||||||
|
|
||||||
public static void register(IEventBus eventBus) {
|
public static void register(IEventBus eventBus) {
|
||||||
ITEMS.register(eventBus);
|
ITEMS.register(eventBus);
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package net.banutama.utamacraft.item;
|
||||||
|
|
||||||
|
import dan200.computercraft.shared.Registry;
|
||||||
|
import net.banutama.utamacraft.CCRegistration;
|
||||||
|
import net.minecraft.core.NonNullList;
|
||||||
|
import net.minecraft.world.item.CreativeModeTab;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class PlayerPeripheralItem extends BaseItem {
|
||||||
|
public PlayerPeripheralItem() {
|
||||||
|
super(new Item.Properties().stacksTo(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fillItemCategory(@NotNull CreativeModeTab group, @NotNull NonNullList<ItemStack> items) {
|
||||||
|
super.fillItemCategory(group, items);
|
||||||
|
|
||||||
|
if (allowedIn(group)) {
|
||||||
|
ItemStack turtle_stack = new ItemStack(Registry.ModItems.TURTLE_NORMAL.get());
|
||||||
|
turtle_stack.getOrCreateTag().putString("RightUpgrade", CCRegistration.ID.PLAYER_TURTLE.toString());
|
||||||
|
items.add(turtle_stack);
|
||||||
|
|
||||||
|
ItemStack advanced_turtle_stack = new ItemStack(Registry.ModItems.TURTLE_ADVANCED.get());
|
||||||
|
advanced_turtle_stack.getOrCreateTag().putString("RightUpgrade", CCRegistration.ID.PLAYER_TURTLE.toString());
|
||||||
|
items.add(advanced_turtle_stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package net.banutama.utamacraft.util;
|
||||||
|
|
||||||
|
import com.mojang.authlib.GameProfile;
|
||||||
|
import net.banutama.utamacraft.Utamacraft;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class FakeGameProfile extends GameProfile {
|
||||||
|
private static final UUID GAME_PROFILE_UUID = UUID.nameUUIDFromBytes("Utamacraft".getBytes(StandardCharsets.UTF_8));
|
||||||
|
private static final String GAME_PROFILE_NAME = String.format("[%s]", Utamacraft.MOD_ID);
|
||||||
|
|
||||||
|
public FakeGameProfile() {
|
||||||
|
super(GAME_PROFILE_UUID, GAME_PROFILE_NAME);
|
||||||
|
}
|
||||||
|
}
|
192
src/main/java/net/banutama/utamacraft/util/SimpleFakePlayer.java
Normal file
192
src/main/java/net/banutama/utamacraft/util/SimpleFakePlayer.java
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
package net.banutama.utamacraft.util;
|
||||||
|
|
||||||
|
import com.mojang.authlib.GameProfile;
|
||||||
|
import net.banutama.utamacraft.Utamacraft;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.InteractionHand;
|
||||||
|
import net.minecraft.world.InteractionResult;
|
||||||
|
import net.minecraft.world.MenuProvider;
|
||||||
|
import net.minecraft.world.effect.MobEffectInstance;
|
||||||
|
import net.minecraft.world.entity.*;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.level.BlockGetter;
|
||||||
|
import net.minecraft.world.level.ClipContext;
|
||||||
|
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
||||||
|
import net.minecraft.world.phys.*;
|
||||||
|
import net.minecraftforge.common.util.FakePlayer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.OptionalInt;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
public class SimpleFakePlayer extends FakePlayer {
|
||||||
|
private static WeakReference<SimpleFakePlayer> INSTANCE;
|
||||||
|
|
||||||
|
public SimpleFakePlayer(ServerLevel world, GameProfile profile) {
|
||||||
|
super(world, profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleFakePlayer(ServerLevel world) {
|
||||||
|
this(world, new FakeGameProfile());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <R> R withFakePlayer(ServerLevel world, Function<SimpleFakePlayer, R> consumer) {
|
||||||
|
SimpleFakePlayer player = INSTANCE == null ? null : INSTANCE.get();
|
||||||
|
if (player == null) {
|
||||||
|
player = new SimpleFakePlayer(world);
|
||||||
|
INSTANCE = new WeakReference<>(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumer.apply(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HitResult findHit(int range, boolean skipEntity, boolean skipBlock, Predicate<Entity> entityFilter) {
|
||||||
|
Vec3 origin = new Vec3(getX(), getY(), getZ());
|
||||||
|
Vec3 look = getLookAngle();
|
||||||
|
Vec3 target = new Vec3(origin.x + look.x * range, origin.y + look.y * range, origin.z + look.z * range);
|
||||||
|
ClipContext traceContext = new ClipContext(origin, target, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this);
|
||||||
|
Vec3 directionVec = traceContext.getFrom().subtract(traceContext.getTo());
|
||||||
|
Direction traceDirection = Direction.getNearest(directionVec.x, directionVec.y, directionVec.z);
|
||||||
|
|
||||||
|
HitResult blockHit = null;
|
||||||
|
if (skipBlock) {
|
||||||
|
Vec3 to = traceContext.getTo();
|
||||||
|
blockHit = BlockHitResult.miss(to, traceDirection, new BlockPos(to));
|
||||||
|
} else {
|
||||||
|
blockHit = BlockGetter.traverseBlocks(traceContext.getFrom(), traceContext.getTo(), traceContext, (clipContext, pos) -> {
|
||||||
|
if (level.isEmptyBlock(pos)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new BlockHitResult(new Vec3(pos.getX(), pos.getY(), pos.getZ()), traceDirection, pos, false);
|
||||||
|
}, clipContext -> BlockHitResult.miss(clipContext.getTo(), traceDirection, new BlockPos(clipContext.getTo())));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skipEntity) {
|
||||||
|
return blockHit;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Entity> entities =
|
||||||
|
level.getEntities(
|
||||||
|
this,
|
||||||
|
this.getBoundingBox()
|
||||||
|
.expandTowards(look.x * range, look.y * range, look.z * range)
|
||||||
|
.inflate(1.0, 1.0, 1.0),
|
||||||
|
EntitySelector.NO_SPECTATORS);
|
||||||
|
|
||||||
|
LivingEntity closestEntity = null;
|
||||||
|
Vec3 closestVec = null;
|
||||||
|
double closestDistance = 0.0;
|
||||||
|
|
||||||
|
for (Entity entityHit : entities) {
|
||||||
|
if (!(entityHit instanceof LivingEntity living)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entityFilter != null && !entityFilter.test(entityHit)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AABB box = entityHit.getBoundingBox().inflate(entityHit.getPickRadius() + 0.5);
|
||||||
|
Optional<Vec3> clipResult = box.clip(origin, target);
|
||||||
|
|
||||||
|
if (box.contains(origin)) {
|
||||||
|
if (closestDistance >= 0.0) {
|
||||||
|
closestEntity = living;
|
||||||
|
closestVec = clipResult.orElse(origin);
|
||||||
|
closestDistance = 0.0;
|
||||||
|
}
|
||||||
|
} else if (clipResult.isPresent()) {
|
||||||
|
Vec3 clipVec = clipResult.get();
|
||||||
|
double distance = origin.distanceTo(clipVec);
|
||||||
|
|
||||||
|
if (distance < closestDistance || closestDistance == 0.0) {
|
||||||
|
if (entityHit == entityHit.getRootVehicle()) {
|
||||||
|
if (closestDistance == 0.0) {
|
||||||
|
closestEntity = living;
|
||||||
|
closestVec = clipVec;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
closestEntity = living;
|
||||||
|
closestVec = clipVec;
|
||||||
|
closestDistance = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closestEntity != null &&
|
||||||
|
closestDistance <= range &&
|
||||||
|
(blockHit.getType() == HitResult.Type.MISS ||
|
||||||
|
distanceToSqr(blockHit.getLocation()) > closestDistance * closestDistance)) {
|
||||||
|
return new EntityHitResult(closestEntity, closestVec);
|
||||||
|
} else {
|
||||||
|
return blockHit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public InteractionResult use(int range, boolean skipEntity, boolean skipBlock, Predicate<Entity> entityFilter) {
|
||||||
|
HitResult hit = findHit(range, skipEntity, skipBlock, entityFilter);
|
||||||
|
if (hit instanceof BlockHitResult blockHit) {
|
||||||
|
InteractionResult res =
|
||||||
|
gameMode.useItemOn(this, level, getMainHandItem(), InteractionHand.MAIN_HAND, blockHit);
|
||||||
|
if (res.consumesAction()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gameMode.useItem(this, level, getMainHandItem(), InteractionHand.MAIN_HAND);
|
||||||
|
} else if (hit instanceof EntityHitResult) {
|
||||||
|
// TODO: Interact with an entity?
|
||||||
|
return InteractionResult.FAIL;
|
||||||
|
} else {
|
||||||
|
return InteractionResult.FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Overrides to compensate for FakePlayer
|
||||||
|
//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeAffected(@NotNull MobEffectInstance effect) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canHarmPlayer(Player player) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean startRiding(@NotNull Entity entity, boolean b) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull OptionalInt openMenu(@Nullable MenuProvider provider) {
|
||||||
|
return OptionalInt.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getStandingEyeHeight(@NotNull Pose pose, @NotNull EntityDimensions dimensions) {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getEyeY() {
|
||||||
|
return getY() + 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getAttackStrengthScale(float f) {
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
{
|
{
|
||||||
|
"block.utamacraft.ethereal_glass": "Ethereal Glass",
|
||||||
|
"item.utamacraft.player_peripheral": "Player peripheral",
|
||||||
"item.utamacraft.utamacraft_logo": "Utamacraft",
|
"item.utamacraft.utamacraft_logo": "Utamacraft",
|
||||||
"itemGroup.utamacraft_tab": "Utamacraft",
|
"itemGroup.utamacraft_tab": "Utamacraft",
|
||||||
"block.utamacraft.ethereal_glass": "Ethereal Glass",
|
"tooltip.utamacraft.ethereal_glass": "Glass that is not solid to players",
|
||||||
"tooltip.utamacraft.ethereal_glass": "Glass that is not solid to players"
|
"turtle.utamacraft.player_turtle": "Player"
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "utamacraft:item/player_peripheral"
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"type": "utamacraft:player_turtle",
|
||||||
|
"item": "utamacraft:player_peripheral"
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"type": "minecraft:crafting_shaped",
|
||||||
|
"pattern": [
|
||||||
|
"GRG",
|
||||||
|
"R.R",
|
||||||
|
"GRG"
|
||||||
|
],
|
||||||
|
"key": {
|
||||||
|
"G": {
|
||||||
|
"item": "minecraft:gold_ingot"
|
||||||
|
},
|
||||||
|
"R": {
|
||||||
|
"item": "minecraft:redstone"
|
||||||
|
},
|
||||||
|
".": {
|
||||||
|
"item": "minecraft:ender_eye"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"result": {
|
||||||
|
"item": "utamacraft:player_peripheral",
|
||||||
|
"count": 1
|
||||||
|
}
|
||||||
|
}
|
BIN
textures/player_peripheral.afdesign
Normal file
BIN
textures/player_peripheral.afdesign
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user