Add the player-use peripheral for CC:Tweaked #9
23
build.gradle
23
build.gradle
@ -38,6 +38,11 @@ minecraft {
|
||||
// Default run configurations.
|
||||
// These can be tweaked, removed, or duplicated as needed.
|
||||
runs {
|
||||
configureEach {
|
||||
property 'mixin.env.remapRefMap', 'true'
|
||||
property 'mixin.env.refMapRemappingFile', "${buildDir}/createSrgToMcp/output.srg"
|
||||
}
|
||||
|
||||
client {
|
||||
workingDirectory project.file('run')
|
||||
|
||||
@ -123,6 +128,13 @@ repositories {
|
||||
// flatDir {
|
||||
// dir 'libs'
|
||||
// }
|
||||
|
||||
maven {
|
||||
url "https://squiddev.cc/maven/"
|
||||
content {
|
||||
includeGroup("org.squiddev")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@ -142,6 +154,14 @@ dependencies {
|
||||
// For more info...
|
||||
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
|
||||
// http://www.gradle.org/docs/current/userguide/dependency_management.html
|
||||
|
||||
// Vanilla (i.e. for multi-loader systems)
|
||||
// compileOnly("cc.tweaked:cc-tweaked-${minecraft_version}-common-api:${cct_version}")
|
||||
|
||||
// Forge Gradle
|
||||
// compileOnly("cc.tweaked:cc-tweaked-${minecraft_version}-core-api:${cct_version}")
|
||||
// compileOnly(fg.deobf("cc.tweaked:cc-tweaked-${minecraft_version}-forge-api:${cct_version}"))
|
||||
implementation fg.deobf("org.squiddev:cc-tweaked-${minecraft_version}:${cct_version}")
|
||||
}
|
||||
|
||||
// This task will expand all declared properties from Gradle (gradle.properties) in the specified resource targets.
|
||||
@ -158,7 +178,8 @@ tasks.named('processResources', ProcessResources).configure {
|
||||
mod_license: mod_license,
|
||||
mod_version: mod_version,
|
||||
mod_authors: mod_authors,
|
||||
mod_description: mod_description
|
||||
mod_description: mod_description,
|
||||
cct_version: cct_version
|
||||
]
|
||||
inputs.properties replaceProperties
|
||||
|
||||
|
@ -35,6 +35,11 @@ mapping_channel=official
|
||||
# This must match the format required by the mapping channel.
|
||||
mapping_version=1.19.2
|
||||
|
||||
## Dependency Properties
|
||||
|
||||
# The version of CC:Tweaked we're building against
|
||||
cct_version=1.101.3
|
||||
|
||||
## Mod Properties
|
||||
|
||||
# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63}
|
||||
|
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);
|
||||
ModBlocks.register(bus);
|
||||
CCRegistration.register(bus);
|
||||
|
||||
bus.addListener(this::commonSetup);
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
@ -37,7 +38,7 @@ public class Utamacraft {
|
||||
}
|
||||
|
||||
@Mod.EventBusSubscriber(modid = MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
|
||||
public static class ClientModEvents {
|
||||
public static class ModEvents {
|
||||
@SubscribeEvent
|
||||
public static void onClientSetup(FMLClientSetupEvent event) {
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ public class ModBlocks {
|
||||
DeferredRegister.create(ForgeRegistries.BLOCKS, Utamacraft.MOD_ID);
|
||||
|
||||
public static final RegistryObject<Block> ETHEREAL_GLASS =
|
||||
registerBlock("ethereal_glass", () -> new EtherealGlass());
|
||||
registerBlock("ethereal_glass", EtherealGlass::new);
|
||||
|
||||
private static <T extends Block> RegistryObject<T> registerBlock(String name, Supplier<T> block) {
|
||||
RegistryObject<T> registered_block = BLOCKS.register(name, block);
|
||||
|
@ -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.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -11,7 +10,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class ModCreativeModeTab {
|
||||
public static final CreativeModeTab TAB = new CreativeModeTab("utamacraft_tab") {
|
||||
@Override
|
||||
public ItemStack makeIcon() {
|
||||
public @NotNull ItemStack makeIcon() {
|
||||
return new ItemStack(ModItems.LOGO.get());
|
||||
}
|
||||
};
|
||||
|
@ -11,8 +11,11 @@ public class ModItems {
|
||||
public static final DeferredRegister<Item> ITEMS =
|
||||
DeferredRegister.create(ForgeRegistries.ITEMS, Utamacraft.MOD_ID);
|
||||
|
||||
public static final RegistryObject<Item> LOGO = ITEMS.register("utamacraft_logo",
|
||||
() -> new Item(new Item.Properties()));
|
||||
public static final RegistryObject<Item> LOGO =
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
}
|
@ -46,7 +46,6 @@ authors="${mod_authors}" #optional
|
||||
# The description text for the mod (multi line!) (#mandatory)
|
||||
description='''${mod_description}'''
|
||||
|
||||
# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.
|
||||
[[dependencies.${mod_id}]] #optional
|
||||
# the modid of the dependency
|
||||
modId="forge" #mandatory
|
||||
@ -58,11 +57,17 @@ description='''${mod_description}'''
|
||||
ordering="NONE"
|
||||
# Side this dependency is applied on - BOTH, CLIENT or SERVER
|
||||
side="BOTH"
|
||||
# Here's another dependency
|
||||
|
||||
[[dependencies.${mod_id}]]
|
||||
modId="minecraft"
|
||||
mandatory=true
|
||||
# This version range declares a minimum of the current minecraft version up to but not including the next major version
|
||||
versionRange="${minecraft_version_range}"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
||||
|
||||
[[dependencies.${mod_id}]]
|
||||
modId = "computercraft"
|
||||
mandatory = true
|
||||
versionRange = "[${cct_version},)"
|
||||
ordering = "NONE"
|
||||
side = "BOTH"
|
@ -1,6 +1,8 @@
|
||||
{
|
||||
"block.utamacraft.ethereal_glass": "Ethereal Glass",
|
||||
"item.utamacraft.player_peripheral": "Player peripheral",
|
||||
"item.utamacraft.utamacraft_logo": "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