mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-10 12:33:57 +01:00
ComputerCraft integration for Display Links
- CC computers can now control display links through a variety of functions - Added ComputerControllable interface to define a tile entity as controllable by CC computers - Added CC: Tweaked soft dependency
This commit is contained in:
parent
5303d69bf1
commit
6591c2d46e
11
build.gradle
11
build.gradle
@ -135,6 +135,14 @@ repositories {
|
|||||||
includeGroup "maven.modrinth"
|
includeGroup "maven.modrinth"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
maven {
|
||||||
|
// Location of maven for CC: Tweaked
|
||||||
|
name = "squiddev"
|
||||||
|
url = "https://squiddev.cc/maven/"
|
||||||
|
content {
|
||||||
|
includeGroup "org.squiddev"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -162,6 +170,9 @@ dependencies {
|
|||||||
compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_minecraft_version}-${curios_version}:api")
|
compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_minecraft_version}-${curios_version}:api")
|
||||||
runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_minecraft_version}-${curios_version}")
|
runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_minecraft_version}-${curios_version}")
|
||||||
|
|
||||||
|
compileOnly fg.deobf("org.squiddev:cc-tweaked-${cc_tweaked_minecraft_version}:${cc_tweaked_version}:api")
|
||||||
|
runtimeOnly fg.deobf("org.squiddev:cc-tweaked-${cc_tweaked_minecraft_version}:${cc_tweaked_version}")
|
||||||
|
|
||||||
// implementation fg.deobf("curse.maven:druidcraft-340991:3101903")
|
// implementation fg.deobf("curse.maven:druidcraft-340991:3101903")
|
||||||
// implementation fg.deobf("com.ferreusveritas.dynamictrees:DynamicTrees-1.16.5:0.10.0-Beta25")
|
// implementation fg.deobf("com.ferreusveritas.dynamictrees:DynamicTrees-1.16.5:0.10.0-Beta25")
|
||||||
// runtimeOnly fg.deobf("vazkii.arl:AutoRegLib:1.4-35.69")
|
// runtimeOnly fg.deobf("vazkii.arl:AutoRegLib:1.4-35.69")
|
||||||
|
@ -26,6 +26,8 @@ jei_minecraft_version = 1.18.2
|
|||||||
jei_version = 9.7.0.209
|
jei_version = 9.7.0.209
|
||||||
curios_minecraft_version = 1.18.2
|
curios_minecraft_version = 1.18.2
|
||||||
curios_version = 5.0.7.0
|
curios_version = 5.0.7.0
|
||||||
|
cc_tweaked_minecraft_version = 1.18.2
|
||||||
|
cc_tweaked_version = 1.100.10
|
||||||
|
|
||||||
# curseforge information
|
# curseforge information
|
||||||
projectId = 328085
|
projectId = 328085
|
||||||
|
@ -13,7 +13,9 @@ import net.minecraftforge.fml.ModList;
|
|||||||
public enum Mods {
|
public enum Mods {
|
||||||
DYNAMICTREES,
|
DYNAMICTREES,
|
||||||
TCONSTRUCT,
|
TCONSTRUCT,
|
||||||
CURIOS;
|
CURIOS,
|
||||||
|
|
||||||
|
COMPUTERCRAFT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a boolean of whether the mod is loaded or not based on mod id
|
* @return a boolean of whether the mod is loaded or not based on mod id
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.simibubi.create.compat.computercraft;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.common.capabilities.CapabilityManager;
|
||||||
|
import net.minecraftforge.common.capabilities.CapabilityToken;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
|
||||||
|
public interface ComputerControllable {
|
||||||
|
|
||||||
|
Capability<IPeripheral> PERIPHERAL_CAPABILITY = CapabilityManager.get(new CapabilityToken<>() {});
|
||||||
|
|
||||||
|
IPeripheral createPeripheral();
|
||||||
|
|
||||||
|
void setPeripheralHandler(LazyOptional<IPeripheral> peripheralHandler);
|
||||||
|
|
||||||
|
LazyOptional<IPeripheral> getPeripheralHandler();
|
||||||
|
|
||||||
|
default <T> LazyOptional<T> getPeripheralCapability(@NotNull Capability<T> cap) {
|
||||||
|
if (cap == PERIPHERAL_CAPABILITY) {
|
||||||
|
if (getPeripheralHandler() == null || !getPeripheralHandler().isPresent())
|
||||||
|
setPeripheralHandler(LazyOptional.of(this::createPeripheral));
|
||||||
|
|
||||||
|
return getPeripheralHandler().cast();
|
||||||
|
}
|
||||||
|
|
||||||
|
return LazyOptional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
default void removePeripheral() {
|
||||||
|
if (getPeripheralHandler() != null)
|
||||||
|
getPeripheralHandler().invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,135 @@
|
|||||||
|
package com.simibubi.create.compat.computercraft;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.display.DisplayLinkTileEntity;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.IArguments;
|
||||||
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
|
import dan200.computercraft.api.lua.LuaFunction;
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.StringTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
|
||||||
|
public class DisplayLinkPeripheral implements IPeripheral {
|
||||||
|
|
||||||
|
public static final String TAG_KEY = "ComputerSourceList";
|
||||||
|
|
||||||
|
private final DisplayLinkTileEntity tile;
|
||||||
|
|
||||||
|
public DisplayLinkPeripheral(DisplayLinkTileEntity tile) {
|
||||||
|
this.tile = tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public void writeLine(String line) {
|
||||||
|
ListTag tag = this.tile.getSourceConfig().getList(TAG_KEY, Tag.TAG_STRING);
|
||||||
|
tag.add(StringTag.valueOf(line));
|
||||||
|
|
||||||
|
this.tile.getSourceConfig().put(TAG_KEY, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public void setLine(int lineNumber, String line) {
|
||||||
|
ListTag tag = this.tile.getSourceConfig().getList(TAG_KEY, Tag.TAG_STRING);
|
||||||
|
int size = tag.size();
|
||||||
|
|
||||||
|
if (lineNumber < size) {
|
||||||
|
tag.set(lineNumber, StringTag.valueOf(line));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < lineNumber - size; i++) {
|
||||||
|
tag.add(StringTag.valueOf(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
tag.add(StringTag.valueOf(line));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tile.getSourceConfig().put(TAG_KEY, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public void writeLines(IArguments arguments) throws LuaException {
|
||||||
|
ListTag tag = this.tile.getSourceConfig().getList(TAG_KEY, Tag.TAG_STRING);
|
||||||
|
List<String> lines = getLinesFromArguments(arguments, 0);
|
||||||
|
|
||||||
|
for (String line : lines) {
|
||||||
|
tag.add(StringTag.valueOf(line));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tile.getSourceConfig().put(TAG_KEY, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public void setLines(IArguments arguments) throws LuaException {
|
||||||
|
ListTag tag = this.tile.getSourceConfig().getList(TAG_KEY, Tag.TAG_STRING);
|
||||||
|
List<String> lines = getLinesFromArguments(arguments, 1);
|
||||||
|
|
||||||
|
int size = tag.size();
|
||||||
|
int lineNumber = arguments.getInt(0);
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (int j = lineNumber; j < Math.min(size, lines.size()); j++) {
|
||||||
|
tag.set(j, StringTag.valueOf(lines.get(i)));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < lineNumber - size; j++) {
|
||||||
|
tag.add(StringTag.valueOf(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = i; j < lines.size(); j++) {
|
||||||
|
tag.add(StringTag.valueOf(lines.get(i)));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tile.getSourceConfig().put(TAG_KEY, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction
|
||||||
|
public void clear() {
|
||||||
|
this.tile.getSourceConfig().put(TAG_KEY, new ListTag());
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaFunction(mainThread = true)
|
||||||
|
public void update() {
|
||||||
|
this.tile.tickSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getLinesFromArguments(IArguments arguments, int offset) throws LuaException {
|
||||||
|
List<String> lines = new ArrayList<>();
|
||||||
|
|
||||||
|
if (arguments.count() > offset + 1) {
|
||||||
|
for (int i = offset; i < arguments.count(); i++) {
|
||||||
|
lines.add(arguments.getString(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Map<?, ?> map = arguments.getTable(offset);
|
||||||
|
|
||||||
|
for (Object line : map.values()) {
|
||||||
|
lines.add(line.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return "cdl";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable IPeripheral other) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -9,6 +9,8 @@ import java.util.Map;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
|
import com.simibubi.create.compat.Mods;
|
||||||
|
import com.simibubi.create.content.logistics.block.display.source.ComputerDisplaySource;
|
||||||
import com.simibubi.create.content.logistics.block.display.source.DeathCounterDisplaySource;
|
import com.simibubi.create.content.logistics.block.display.source.DeathCounterDisplaySource;
|
||||||
import com.simibubi.create.content.logistics.block.display.source.DisplaySource;
|
import com.simibubi.create.content.logistics.block.display.source.DisplaySource;
|
||||||
import com.simibubi.create.content.logistics.block.display.source.EnchantPowerDisplaySource;
|
import com.simibubi.create.content.logistics.block.display.source.EnchantPowerDisplaySource;
|
||||||
@ -237,5 +239,12 @@ public class AllDisplayBehaviours {
|
|||||||
assignTile(register(Create.asResource("scoreboard_display_source"), new ScoreboardDisplaySource()), BlockEntityType.COMMAND_BLOCK);
|
assignTile(register(Create.asResource("scoreboard_display_source"), new ScoreboardDisplaySource()), BlockEntityType.COMMAND_BLOCK);
|
||||||
assignTile(register(Create.asResource("enchant_power_display_source"), new EnchantPowerDisplaySource()), BlockEntityType.ENCHANTING_TABLE);
|
assignTile(register(Create.asResource("enchant_power_display_source"), new EnchantPowerDisplaySource()), BlockEntityType.ENCHANTING_TABLE);
|
||||||
assignBlock(register(Create.asResource("redstone_power_display_source"), new RedstonePowerDisplaySource()), Blocks.TARGET);
|
assignBlock(register(Create.asResource("redstone_power_display_source"), new RedstonePowerDisplaySource()), Blocks.TARGET);
|
||||||
|
|
||||||
|
Mods.COMPUTERCRAFT.executeIfInstalled(() -> () -> {
|
||||||
|
DisplayBehaviour computerDisplaySource = register(Create.asResource("computer_display_source"), new ComputerDisplaySource());
|
||||||
|
|
||||||
|
assignTile(computerDisplaySource, new ResourceLocation(Mods.COMPUTERCRAFT.asId(), "wired_modem_full"));
|
||||||
|
assignTile(computerDisplaySource, new ResourceLocation("computercraft", "wired_modem"));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,11 @@ package com.simibubi.create.content.logistics.block.display;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.simibubi.create.compat.computercraft.ComputerControllable;
|
||||||
|
import com.simibubi.create.compat.computercraft.DisplayLinkPeripheral;
|
||||||
import com.simibubi.create.content.logistics.block.display.source.DisplaySource;
|
import com.simibubi.create.content.logistics.block.display.source.DisplaySource;
|
||||||
import com.simibubi.create.content.logistics.block.display.target.DisplayTarget;
|
import com.simibubi.create.content.logistics.block.display.target.DisplayTarget;
|
||||||
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
import com.simibubi.create.foundation.advancement.AllAdvancements;
|
||||||
@ -11,6 +16,7 @@ import com.simibubi.create.foundation.utility.NBTHelper;
|
|||||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
|
||||||
import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
|
import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
@ -18,8 +24,10 @@ import net.minecraft.nbt.NbtUtils;
|
|||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
|
|
||||||
public class DisplayLinkTileEntity extends SmartTileEntity {
|
public class DisplayLinkTileEntity extends SmartTileEntity implements ComputerControllable {
|
||||||
|
|
||||||
protected BlockPos targetOffset;
|
protected BlockPos targetOffset;
|
||||||
|
|
||||||
@ -31,9 +39,11 @@ public class DisplayLinkTileEntity extends SmartTileEntity {
|
|||||||
|
|
||||||
public LerpedFloat glow;
|
public LerpedFloat glow;
|
||||||
private boolean sendPulse;
|
private boolean sendPulse;
|
||||||
|
|
||||||
public int refreshTicks;
|
public int refreshTicks;
|
||||||
|
|
||||||
|
private LazyOptional<IPeripheral> peripheralHandler;
|
||||||
|
|
||||||
public DisplayLinkTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
public DisplayLinkTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||||
super(type, pos, state);
|
super(type, pos, state);
|
||||||
targetOffset = BlockPos.ZERO;
|
targetOffset = BlockPos.ZERO;
|
||||||
@ -47,7 +57,7 @@ public class DisplayLinkTileEntity extends SmartTileEntity {
|
|||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
|
|
||||||
if (isVirtual()) {
|
if (isVirtual()) {
|
||||||
glow.tickChaser();
|
glow.tickChaser();
|
||||||
return;
|
return;
|
||||||
@ -59,9 +69,9 @@ public class DisplayLinkTileEntity extends SmartTileEntity {
|
|||||||
glow.tickChaser();
|
glow.tickChaser();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshTicks++;
|
refreshTicks++;
|
||||||
if (refreshTicks < activeSource.getPassiveRefreshTicks())
|
if (refreshTicks < activeSource.getPassiveRefreshTicks() || !activeSource.shouldPassiveReset())
|
||||||
return;
|
return;
|
||||||
tickSource();
|
tickSource();
|
||||||
}
|
}
|
||||||
@ -114,7 +124,7 @@ public class DisplayLinkTileEntity extends SmartTileEntity {
|
|||||||
activeSource.transferData(context, activeTarget, targetLine);
|
activeSource.transferData(context, activeTarget, targetLine);
|
||||||
sendPulse = true;
|
sendPulse = true;
|
||||||
sendData();
|
sendData();
|
||||||
|
|
||||||
award(AllAdvancements.DISPLAY_LINK);
|
award(AllAdvancements.DISPLAY_LINK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +143,7 @@ public class DisplayLinkTileEntity extends SmartTileEntity {
|
|||||||
protected void write(CompoundTag tag, boolean clientPacket) {
|
protected void write(CompoundTag tag, boolean clientPacket) {
|
||||||
super.write(tag, clientPacket);
|
super.write(tag, clientPacket);
|
||||||
writeGatheredData(tag);
|
writeGatheredData(tag);
|
||||||
if (clientPacket && activeTarget != null)
|
if (clientPacket && activeTarget != null)
|
||||||
tag.putString("TargetType", activeTarget.id.toString());
|
tag.putString("TargetType", activeTarget.id.toString());
|
||||||
if (clientPacket && sendPulse) {
|
if (clientPacket && sendPulse) {
|
||||||
sendPulse = false;
|
sendPulse = false;
|
||||||
@ -173,6 +183,35 @@ public class DisplayLinkTileEntity extends SmartTileEntity {
|
|||||||
sourceConfig = data.copy();
|
sourceConfig = data.copy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
|
||||||
|
LazyOptional<T> peripheralCap = getPeripheralCapability(cap);
|
||||||
|
|
||||||
|
return peripheralCap.isPresent() ? peripheralCap : super.getCapability(cap, side);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRemoved() {
|
||||||
|
super.setRemoved();
|
||||||
|
removePeripheral();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPeripheral createPeripheral() {
|
||||||
|
return new DisplayLinkPeripheral(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPeripheralHandler(LazyOptional<IPeripheral> peripheralHandler) {
|
||||||
|
this.peripheralHandler = peripheralHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LazyOptional<IPeripheral> getPeripheralHandler() {
|
||||||
|
return this.peripheralHandler;
|
||||||
|
}
|
||||||
|
|
||||||
public void target(BlockPos targetPosition) {
|
public void target(BlockPos targetPosition) {
|
||||||
this.targetOffset = targetPosition.subtract(worldPosition);
|
this.targetOffset = targetPosition.subtract(worldPosition);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.simibubi.create.content.logistics.block.display.source;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.simibubi.create.content.logistics.block.display.DisplayLinkContext;
|
||||||
|
import com.simibubi.create.content.logistics.block.display.target.DisplayTargetStats;
|
||||||
|
import com.simibubi.create.foundation.utility.Components;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
|
||||||
|
public class ComputerDisplaySource extends DisplaySource {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MutableComponent> provideText(DisplayLinkContext context, DisplayTargetStats stats) {
|
||||||
|
List<MutableComponent> components = new ArrayList<>();
|
||||||
|
ListTag tag = context.sourceConfig().getList("ComputerSourceList", Tag.TAG_STRING);
|
||||||
|
|
||||||
|
for (int i = 0; i < tag.size(); i++) {
|
||||||
|
components.add(Components.literal(tag.getString(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return components;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPassiveReset() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -49,6 +49,10 @@ public abstract class DisplaySource extends DisplayBehaviour {
|
|||||||
return 100;
|
return 100;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public boolean shouldPassiveReset() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected String getTranslationKey() {
|
protected String getTranslationKey() {
|
||||||
return id.getPath();
|
return id.getPath();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user