mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-22 09:17:39 +00:00
feature(fabric): added fabric support (#491)
* Initial work towards Fabric compat. This does not compile yet * Further updates - should compile but Gradle is being weird. * Remove useless buildscript extras * Added mixins to buildscript classpath to fix Loom crash * Make it compile * Got it building and added interaction * Fixed review comments * Use ServerPlayerEntity for FakePlayer * Use method references for nicer names * Fixed remaining comments and added networking for CUI * Output as dist.jar * Added mixins for left click air * Use regex for cleanliness
This commit is contained in:
parent
7d558ccffa
commit
aa8d34c913
@ -30,7 +30,7 @@ println """
|
||||
1) Read COMPILING.md if you haven't yet
|
||||
2) Try running 'build' in a separate Gradle run
|
||||
3) Use gradlew and not gradle
|
||||
4) If you still need help, ask on IRC! irc.esper.net #sk89q
|
||||
4) If you still need help, ask on Discord! https://discord.gg/enginehub
|
||||
|
||||
Output files will be in [subproject]/build/libs
|
||||
*******************************************
|
||||
@ -85,7 +85,7 @@ subprojects {
|
||||
}
|
||||
}
|
||||
|
||||
configure(['core', 'bukkit', 'forge', 'sponge'].collect { project(":worldedit-$it") }) {
|
||||
configure(['core', 'bukkit', 'forge', 'sponge', 'fabric'].collect { project(":worldedit-$it") }) {
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'maven'
|
||||
apply plugin: 'checkstyle'
|
||||
@ -118,7 +118,7 @@ configure(['core', 'bukkit', 'forge', 'sponge'].collect { project(":worldedit-$i
|
||||
archives javadocJar
|
||||
}
|
||||
|
||||
if (!(name.equals('worldedit-forge') || name.equals('worldedit-sponge'))) {
|
||||
if (name == "worldedit-core" || name == "worldedit-bukkit") {
|
||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||
classifier = 'sources'
|
||||
from sourceSets.main.allSource
|
||||
@ -144,7 +144,7 @@ configure(['core', 'bukkit', 'forge', 'sponge'].collect { project(":worldedit-$i
|
||||
}
|
||||
}
|
||||
|
||||
configure(['bukkit', 'forge', 'sponge'].collect { project(":worldedit-$it") }) {
|
||||
configure(['bukkit', 'forge', 'sponge', 'fabric'].collect { project(":worldedit-$it") }) {
|
||||
shadowJar {
|
||||
classifier 'dist'
|
||||
dependencies {
|
||||
|
@ -60,6 +60,18 @@
|
||||
<allow pkg="com.mojang.datafixers" />
|
||||
</subpackage>
|
||||
|
||||
<subpackage name="fabric">
|
||||
<allow pkg="net.minecraft"/>
|
||||
<allow pkg="net.fabricmc"/>
|
||||
<allow pkg="com.mojang.authlib"/>
|
||||
<allow pkg="org.apache.logging.log4j"/>
|
||||
<allow pkg="org.lwjgl"/>
|
||||
<allow pkg="io.netty.buffer"/>
|
||||
<allow pkg="org.spongepowered" />
|
||||
<allow pkg="com.mojang.brigadier" />
|
||||
<allow pkg="com.mojang.datafixers" />
|
||||
</subpackage>
|
||||
|
||||
<subpackage name="sponge">
|
||||
<allow pkg="net.minecraft"/>
|
||||
<allow pkg="com.google.inject" />
|
||||
|
@ -2,7 +2,7 @@ rootProject.name = 'worldedit'
|
||||
|
||||
include 'worldedit-libs'
|
||||
|
||||
['bukkit', 'core', 'forge', 'sponge'].forEach {
|
||||
['bukkit', 'core', 'forge', 'sponge', 'fabric'].forEach {
|
||||
include "worldedit-libs:$it"
|
||||
include "worldedit-$it"
|
||||
}
|
||||
|
105
worldedit-fabric/build.gradle
Normal file
105
worldedit-fabric/build.gradle
Normal file
@ -0,0 +1,105 @@
|
||||
import net.fabricmc.loom.task.RemapJarTask
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
name = 'Fabric'
|
||||
url = 'https://maven.fabricmc.net/'
|
||||
}
|
||||
maven {
|
||||
name = 'sponge'
|
||||
url = 'https://repo.spongepowered.org/maven'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'net.fabricmc:fabric-loom:0.2.4-SNAPSHOT'
|
||||
classpath 'org.spongepowered:mixin:0.7.11-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'fabric-loom'
|
||||
|
||||
def minecraftVersion = "1.14.2"
|
||||
def fabricVersion = "0.3.0+build.185"
|
||||
def yarnMappings = "1.14.2+build.7"
|
||||
def loaderVersion = "0.4.8+build.155"
|
||||
|
||||
configurations.all { Configuration it ->
|
||||
it.resolutionStrategy { ResolutionStrategy rs ->
|
||||
rs.force("com.google.guava:guava:21.0")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':worldedit-core')
|
||||
compile 'org.apache.logging.log4j:log4j-slf4j-impl:2.8.1'
|
||||
|
||||
minecraft "com.mojang:minecraft:${minecraftVersion}"
|
||||
mappings "net.fabricmc:yarn:${yarnMappings}"
|
||||
modCompile "net.fabricmc:fabric-loader:${loaderVersion}"
|
||||
|
||||
modCompile "net.fabricmc.fabric-api:fabric-api:${fabricVersion}"
|
||||
|
||||
testCompile group: 'org.mockito', name: 'mockito-core', version: '1.9.0-rc1'
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
|
||||
minecraft {
|
||||
}
|
||||
|
||||
project.archivesBaseName = "${project.archivesBaseName}-mc${minecraftVersion}"
|
||||
|
||||
processResources {
|
||||
// this will ensure that this task is redone when the versions change.
|
||||
inputs.property 'version', project.internalVersion
|
||||
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
include "fabric.mod.json"
|
||||
expand "version": project.internalVersion
|
||||
}
|
||||
|
||||
// copy everything else except the mod json
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
exclude "fabric.mod.json"
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes("Class-Path": "truezip.jar WorldEdit/truezip.jar js.jar WorldEdit/js.jar",
|
||||
"WorldEdit-Version": version)
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
classifier = 'dist-dev'
|
||||
dependencies {
|
||||
relocate "org.slf4j", "com.sk89q.worldedit.slf4j"
|
||||
relocate "org.apache.logging.slf4j", "com.sk89q.worldedit.log4jbridge"
|
||||
|
||||
include(dependency('org.slf4j:slf4j-api'))
|
||||
include(dependency("org.apache.logging.log4j:log4j-slf4j-impl"))
|
||||
}
|
||||
}
|
||||
|
||||
task deobfJar(type: Jar) {
|
||||
from sourceSets.main.output
|
||||
classifier = 'dev'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives deobfJar
|
||||
}
|
||||
|
||||
task shadowJarRemap(type: RemapJarTask) {
|
||||
input shadowJar.archivePath
|
||||
output new File(shadowJar.archivePath.getAbsolutePath().replaceFirst('-dev\\.jar$', ".jar"))
|
||||
}
|
||||
|
||||
shadowJarRemap.dependsOn(shadowJar)
|
||||
build.dependsOn(shadowJarRemap)
|
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import static com.sk89q.worldedit.fabric.FabricAdapter.adaptPlayer;
|
||||
import static net.minecraft.server.command.CommandManager.argument;
|
||||
import static net.minecraft.server.command.CommandManager.literal;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.brigadier.Command;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.context.StringRange;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.suggestion.Suggestion;
|
||||
import com.mojang.brigadier.suggestion.Suggestions;
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.event.platform.CommandSuggestionEvent;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.internal.util.Substring;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import org.enginehub.piston.inject.InjectedValueStore;
|
||||
import org.enginehub.piston.inject.Key;
|
||||
import org.enginehub.piston.inject.MapBackedValueStore;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
|
||||
public final class CommandWrapper {
|
||||
|
||||
private CommandWrapper() {
|
||||
}
|
||||
|
||||
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, org.enginehub.piston.Command command) {
|
||||
ImmutableList.Builder<String> aliases = ImmutableList.builder();
|
||||
aliases.add(command.getName()).addAll(command.getAliases());
|
||||
|
||||
Command<ServerCommandSource> commandRunner =
|
||||
ctx -> {
|
||||
WorldEdit.getInstance().getEventBus().post(new com.sk89q.worldedit.event.platform.CommandEvent(
|
||||
adaptPlayer(ctx.getSource().getPlayer()),
|
||||
ctx.getInput()
|
||||
));
|
||||
return 0;
|
||||
};
|
||||
|
||||
for (String alias : aliases.build()) {
|
||||
LiteralArgumentBuilder<ServerCommandSource> base = literal(alias).executes(commandRunner)
|
||||
.then(argument("args", StringArgumentType.greedyString())
|
||||
.suggests(CommandWrapper::suggest)
|
||||
.executes(commandRunner));
|
||||
if (command.getCondition() != org.enginehub.piston.Command.Condition.TRUE) {
|
||||
base.requires(requirementsFor(command));
|
||||
}
|
||||
dispatcher.register(base);
|
||||
}
|
||||
}
|
||||
|
||||
private static Predicate<ServerCommandSource> requirementsFor(org.enginehub.piston.Command mapping) {
|
||||
return ctx -> {
|
||||
final Entity entity = ctx.getEntity();
|
||||
if (!(entity instanceof ServerPlayerEntity)) {
|
||||
return true;
|
||||
}
|
||||
final Actor actor = FabricAdapter.adaptPlayer(((ServerPlayerEntity) entity));
|
||||
InjectedValueStore store = MapBackedValueStore.create();
|
||||
store.injectValue(Key.of(Actor.class), context -> Optional.of(actor));
|
||||
return mapping.getCondition().satisfied(store);
|
||||
};
|
||||
}
|
||||
|
||||
private static CompletableFuture<Suggestions> suggest(CommandContext<ServerCommandSource> context,
|
||||
SuggestionsBuilder builder) throws CommandSyntaxException {
|
||||
CommandSuggestionEvent event = new CommandSuggestionEvent(
|
||||
FabricAdapter.adaptPlayer(context.getSource().getPlayer()),
|
||||
builder.getInput()
|
||||
);
|
||||
WorldEdit.getInstance().getEventBus().post(event);
|
||||
List<Substring> suggestions = event.getSuggestions();
|
||||
|
||||
ImmutableList.Builder<Suggestion> result = ImmutableList.builder();
|
||||
|
||||
for (Substring suggestion : suggestions) {
|
||||
String suggestionText = suggestion.getSubstring();
|
||||
// If at end, we are actually suggesting the next argument
|
||||
// Ensure there is a space!
|
||||
if (suggestion.getStart() == suggestion.getEnd()
|
||||
&& suggestion.getEnd() == builder.getInput().length()
|
||||
&& !builder.getInput().endsWith(" ")) {
|
||||
suggestionText = " " + suggestionText;
|
||||
}
|
||||
result.add(new Suggestion(
|
||||
StringRange.between(suggestion.getStart(), suggestion.getEnd()),
|
||||
suggestionText
|
||||
));
|
||||
}
|
||||
|
||||
return CompletableFuture.completedFuture(
|
||||
Suggestions.create(builder.getInput(), result.build())
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,241 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.registry.state.BooleanProperty;
|
||||
import com.sk89q.worldedit.registry.state.DirectionalProperty;
|
||||
import com.sk89q.worldedit.registry.state.EnumProperty;
|
||||
import com.sk89q.worldedit.registry.state.IntegerProperty;
|
||||
import com.sk89q.worldedit.registry.state.Property;
|
||||
import com.sk89q.worldedit.util.Direction;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.item.ItemType;
|
||||
import com.sk89q.worldedit.world.item.ItemTypes;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.state.StateFactory;
|
||||
import net.minecraft.state.property.DirectionProperty;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class FabricAdapter {
|
||||
|
||||
private FabricAdapter() {
|
||||
}
|
||||
|
||||
public static World adapt(net.minecraft.world.World world) {
|
||||
return new FabricWorld(world);
|
||||
}
|
||||
|
||||
public static Biome adapt(BiomeType biomeType) {
|
||||
return Registry.BIOME.get(new Identifier(biomeType.getId()));
|
||||
}
|
||||
|
||||
public static BiomeType adapt(Biome biome) {
|
||||
return BiomeTypes.get(Registry.BIOME.getId(biome).toString());
|
||||
}
|
||||
|
||||
public static Vector3 adapt(Vec3d vector) {
|
||||
return Vector3.at(vector.x, vector.y, vector.z);
|
||||
}
|
||||
|
||||
public static BlockVector3 adapt(BlockPos pos) {
|
||||
return BlockVector3.at(pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
public static Vec3d toVec3(BlockVector3 vector) {
|
||||
return new Vec3d(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
|
||||
}
|
||||
|
||||
public static net.minecraft.util.math.Direction adapt(Direction face) {
|
||||
switch (face) {
|
||||
case NORTH: return net.minecraft.util.math.Direction.NORTH;
|
||||
case SOUTH: return net.minecraft.util.math.Direction.SOUTH;
|
||||
case WEST: return net.minecraft.util.math.Direction.WEST;
|
||||
case EAST: return net.minecraft.util.math.Direction.EAST;
|
||||
case DOWN: return net.minecraft.util.math.Direction.DOWN;
|
||||
case UP:
|
||||
default:
|
||||
return net.minecraft.util.math.Direction.UP;
|
||||
}
|
||||
}
|
||||
|
||||
public static Direction adaptEnumFacing(net.minecraft.util.math.Direction face) {
|
||||
switch (face) {
|
||||
case NORTH: return Direction.NORTH;
|
||||
case SOUTH: return Direction.SOUTH;
|
||||
case WEST: return Direction.WEST;
|
||||
case EAST: return Direction.EAST;
|
||||
case DOWN: return Direction.DOWN;
|
||||
case UP:
|
||||
default:
|
||||
return Direction.UP;
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockPos toBlockPos(BlockVector3 vector) {
|
||||
return new BlockPos(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
|
||||
}
|
||||
|
||||
public static Property<?> adaptProperty(net.minecraft.state.property.Property<?> property) {
|
||||
if (property instanceof net.minecraft.state.property.BooleanProperty) {
|
||||
return new BooleanProperty(property.getName(), ImmutableList.copyOf(((net.minecraft.state.property.BooleanProperty) property).getValues()));
|
||||
}
|
||||
if (property instanceof net.minecraft.state.property.IntProperty) {
|
||||
return new IntegerProperty(property.getName(), ImmutableList.copyOf(((net.minecraft.state.property.IntProperty) property).getValues()));
|
||||
}
|
||||
if (property instanceof DirectionProperty) {
|
||||
return new DirectionalProperty(property.getName(), ((DirectionProperty) property).getValues().stream()
|
||||
.map(FabricAdapter::adaptEnumFacing)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
if (property instanceof net.minecraft.state.property.EnumProperty) {
|
||||
// Note: do not make x.asString a method reference.
|
||||
// It will cause runtime bootstrap exceptions.
|
||||
return new EnumProperty(property.getName(), ((net.minecraft.state.property.EnumProperty<?>) property).getValues().stream()
|
||||
.map(x -> x.asString())
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
return new PropertyAdapter<>(property);
|
||||
}
|
||||
|
||||
public static Map<Property<?>, Object> adaptProperties(BlockType block, Map<net.minecraft.state.property.Property<?>, Comparable<?>> mcProps) {
|
||||
Map<Property<?>, Object> props = new TreeMap<>(Comparator.comparing(Property::getName));
|
||||
for (Map.Entry<net.minecraft.state.property.Property<?>, Comparable<?>> prop : mcProps.entrySet()) {
|
||||
Object value = prop.getValue();
|
||||
if (prop.getKey() instanceof DirectionProperty) {
|
||||
value = adaptEnumFacing((net.minecraft.util.math.Direction) value);
|
||||
} else if (prop.getKey() instanceof net.minecraft.state.property.EnumProperty) {
|
||||
value = ((StringIdentifiable) value).asString();
|
||||
}
|
||||
props.put(block.getProperty(prop.getKey().getName()), value);
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
private static net.minecraft.block.BlockState applyProperties(StateFactory<Block, net.minecraft.block.BlockState> stateContainer,
|
||||
net.minecraft.block.BlockState newState, Map<Property<?>, Object> states) {
|
||||
for (Map.Entry<Property<?>, Object> state : states.entrySet()) {
|
||||
net.minecraft.state.property.Property property = stateContainer.getProperty(state.getKey().getName());
|
||||
Comparable value = (Comparable) state.getValue();
|
||||
// we may need to adapt this value, depending on the source prop
|
||||
if (property instanceof DirectionProperty) {
|
||||
Direction dir = (Direction) value;
|
||||
value = adapt(dir);
|
||||
} else if (property instanceof net.minecraft.state.property.EnumProperty) {
|
||||
String enumName = (String) value;
|
||||
value = ((net.minecraft.state.property.EnumProperty<?>) property).getValue((String) value).orElseGet(() -> {
|
||||
throw new IllegalStateException("Enum property " + property.getName() + " does not contain " + enumName);
|
||||
});
|
||||
}
|
||||
|
||||
newState = newState.with(property, value);
|
||||
}
|
||||
return newState;
|
||||
}
|
||||
|
||||
public static net.minecraft.block.BlockState adapt(BlockState blockState) {
|
||||
Block mcBlock = adapt(blockState.getBlockType());
|
||||
net.minecraft.block.BlockState newState = mcBlock.getDefaultState();
|
||||
Map<Property<?>, Object> states = blockState.getStates();
|
||||
return applyProperties(mcBlock.getStateFactory(), newState, states);
|
||||
}
|
||||
|
||||
public static BlockState adapt(net.minecraft.block.BlockState blockState) {
|
||||
BlockType blockType = adapt(blockState.getBlock());
|
||||
return blockType.getState(adaptProperties(blockType, blockState.getEntries()));
|
||||
}
|
||||
|
||||
public static Block adapt(BlockType blockType) {
|
||||
return Registry.BLOCK.get(new Identifier(blockType.getId()));
|
||||
}
|
||||
|
||||
public static BlockType adapt(Block block) {
|
||||
return BlockTypes.get(Registry.BLOCK.getId(block).toString());
|
||||
}
|
||||
|
||||
public static Item adapt(ItemType itemType) {
|
||||
return Registry.ITEM.get(new Identifier(itemType.getId()));
|
||||
}
|
||||
|
||||
public static ItemType adapt(Item item) {
|
||||
return ItemTypes.get(Registry.ITEM.getId(item).toString());
|
||||
}
|
||||
|
||||
public static ItemStack adapt(BaseItemStack baseItemStack) {
|
||||
net.minecraft.nbt.CompoundTag fabricCompound = null;
|
||||
if (baseItemStack.getNbtData() != null) {
|
||||
fabricCompound = NBTConverter.toNative(baseItemStack.getNbtData());
|
||||
}
|
||||
final ItemStack itemStack = new ItemStack(adapt(baseItemStack.getType()), baseItemStack.getAmount());
|
||||
itemStack.setTag(fabricCompound);
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
public static BaseItemStack adapt(ItemStack itemStack) {
|
||||
CompoundTag tag = NBTConverter.fromNative(itemStack.toTag(new net.minecraft.nbt.CompoundTag()));
|
||||
if (tag.getValue().isEmpty()) {
|
||||
tag = null;
|
||||
} else {
|
||||
final Tag tagTag = tag.getValue().get("tag");
|
||||
if (tagTag instanceof CompoundTag) {
|
||||
tag = ((CompoundTag) tagTag);
|
||||
} else {
|
||||
tag = null;
|
||||
}
|
||||
}
|
||||
return new BaseItemStack(adapt(itemStack.getItem()), tag, itemStack.getCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WorldEdit proxy for the given player.
|
||||
*
|
||||
* @param player the player
|
||||
* @return the WorldEdit player
|
||||
*/
|
||||
public static FabricPlayer adaptPlayer(ServerPlayerEntity player) {
|
||||
checkNotNull(player);
|
||||
return new FabricPlayer(player);
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import com.sk89q.worldedit.world.biome.BiomeData;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.registry.BiomeRegistry;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
/**
|
||||
* Provides access to biome data in Fabric.
|
||||
*/
|
||||
class FabricBiomeRegistry implements BiomeRegistry {
|
||||
|
||||
@Override
|
||||
public BiomeData getData(BiomeType biome) {
|
||||
return new FabricBiomeData(FabricAdapter.adapt(biome));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cached biome data information.
|
||||
*/
|
||||
private static class FabricBiomeData implements BiomeData {
|
||||
private final Biome biome;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param biome the base biome
|
||||
*/
|
||||
private FabricBiomeData(Biome biome) {
|
||||
this.biome = biome;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return biome.getTextComponent().getString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import com.sk89q.worldedit.registry.Category;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import com.sk89q.worldedit.world.registry.BlockCategoryRegistry;
|
||||
import net.minecraft.tag.BlockTags;
|
||||
import net.minecraft.tag.Tag;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class FabricBlockCategoryRegistry implements BlockCategoryRegistry {
|
||||
@Override
|
||||
public Set<BlockType> getCategorisedByName(String category) {
|
||||
return Optional.ofNullable(BlockTags.getContainer().get(new Identifier(category)))
|
||||
.map(Tag::values).orElse(Collections.emptySet())
|
||||
.stream().map(FabricAdapter::adapt).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<BlockType> getAll(Category<BlockType> category) {
|
||||
return getCategorisedByName(category.getId());
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
||||
import com.sk89q.worldedit.world.registry.PassthroughBlockMaterial;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.block.piston.PistonBehavior;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Fabric block material that pulls as much info as possible from the Minecraft
|
||||
* Material, and passes the rest to another implementation, typically the
|
||||
* bundled block info.
|
||||
*/
|
||||
public class FabricBlockMaterial extends PassthroughBlockMaterial {
|
||||
|
||||
private final Material delegate;
|
||||
|
||||
public FabricBlockMaterial(Material delegate, @Nullable BlockMaterial secondary) {
|
||||
super(secondary);
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAir() {
|
||||
return delegate == Material.AIR || super.isAir();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpaque() {
|
||||
return delegate.blocksLight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLiquid() {
|
||||
return delegate.isLiquid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid() {
|
||||
return delegate.isSolid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFragileWhenPushed() {
|
||||
return delegate.getPistonBehavior() == PistonBehavior.DESTROY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnpushable() {
|
||||
return delegate.getPistonBehavior() == PistonBehavior.BLOCK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMovementBlocker() {
|
||||
return delegate.blocksMovement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBurnable() {
|
||||
return delegate.isBurnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isToolRequired() {
|
||||
return !delegate.canBreakByHand();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReplacedDuringPlacement() {
|
||||
return delegate.isReplaceable();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import com.sk89q.worldedit.registry.state.Property;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
||||
import com.sk89q.worldedit.world.registry.BundledBlockRegistry;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Material;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class FabricBlockRegistry extends BundledBlockRegistry {
|
||||
|
||||
private Map<Material, FabricBlockMaterial> materialMap = new HashMap<>();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName(BlockType blockType) {
|
||||
Block block = FabricAdapter.adapt(blockType);
|
||||
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
|
||||
return block.getTextComponent().getFormattedText();
|
||||
} else {
|
||||
return super.getName(blockType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockMaterial getMaterial(BlockType blockType) {
|
||||
Block block = FabricAdapter.adapt(blockType);
|
||||
return materialMap.computeIfAbsent(block.getDefaultState().getMaterial(),
|
||||
m -> new FabricBlockMaterial(m, super.getMaterial(blockType)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ? extends Property<?>> getProperties(BlockType blockType) {
|
||||
Block block = FabricAdapter.adapt(blockType);
|
||||
Map<String, Property<?>> map = new TreeMap<>();
|
||||
Collection<net.minecraft.state.property.Property<?>> propertyKeys = block
|
||||
.getDefaultState()
|
||||
.getProperties();
|
||||
for (net.minecraft.state.property.Property<?> key : propertyKeys) {
|
||||
map.put(key.getName(), FabricAdapter.adaptProperty(key));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OptionalInt getInternalBlockStateId(BlockState state) {
|
||||
net.minecraft.block.BlockState equivalent = FabricAdapter.adapt(state);
|
||||
return OptionalInt.of(Block.getRawIdFromState(equivalent));
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import com.sk89q.worldedit.util.PropertiesConfiguration;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class FabricConfiguration extends PropertiesConfiguration {
|
||||
|
||||
public boolean creativeEnable = false;
|
||||
public boolean cheatMode = false;
|
||||
|
||||
public FabricConfiguration(FabricWorldEdit mod) {
|
||||
super(new File(mod.getWorkingDir(), "worldedit.properties"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadExtra() {
|
||||
creativeEnable = getBool("use-in-creative", false);
|
||||
cheatMode = getBool("cheat-mode", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getWorkingDirectory() {
|
||||
return FabricWorldEdit.inst.getWorkingDir();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.entity.metadata.EntityProperties;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.NullWorld;
|
||||
import com.sk89q.worldedit.world.entity.EntityTypes;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
class FabricEntity implements Entity {
|
||||
|
||||
private final WeakReference<net.minecraft.entity.Entity> entityRef;
|
||||
|
||||
FabricEntity(net.minecraft.entity.Entity entity) {
|
||||
checkNotNull(entity);
|
||||
this.entityRef = new WeakReference<>(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseEntity getState() {
|
||||
net.minecraft.entity.Entity entity = entityRef.get();
|
||||
if (entity != null) {
|
||||
Identifier id = Registry.ENTITY_TYPE.getId(entity.getType());
|
||||
CompoundTag tag = new CompoundTag();
|
||||
entity.toTag(tag);
|
||||
return new BaseEntity(EntityTypes.get(id.toString()), NBTConverter.fromNative(tag));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
net.minecraft.entity.Entity entity = entityRef.get();
|
||||
if (entity != null) {
|
||||
Vector3 position = Vector3.at(entity.x, entity.y, entity.z);
|
||||
float yaw = entity.yaw;
|
||||
float pitch = entity.pitch;
|
||||
|
||||
return new Location(FabricAdapter.adapt(entity.world), position, yaw, pitch);
|
||||
} else {
|
||||
return new Location(NullWorld.getInstance());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setLocation(Location location) {
|
||||
// TODO unused atm
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Extent getExtent() {
|
||||
net.minecraft.entity.Entity entity = entityRef.get();
|
||||
if (entity != null) {
|
||||
return FabricAdapter.adapt(entity.world);
|
||||
} else {
|
||||
return NullWorld.getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove() {
|
||||
net.minecraft.entity.Entity entity = entityRef.get();
|
||||
if (entity != null) {
|
||||
entity.remove();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getFacet(Class<? extends T> cls) {
|
||||
net.minecraft.entity.Entity entity = entityRef.get();
|
||||
if (entity != null) {
|
||||
if (EntityProperties.class.isAssignableFrom(cls)) {
|
||||
return (T) new FabricEntityProperties(entity);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.worldedit.entity.metadata.EntityProperties;
|
||||
import net.minecraft.entity.EnderEyeEntity;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.ExperienceOrbEntity;
|
||||
import net.minecraft.entity.FallingBlockEntity;
|
||||
import net.minecraft.entity.ItemEntity;
|
||||
import net.minecraft.entity.Npc;
|
||||
import net.minecraft.entity.TntEntity;
|
||||
import net.minecraft.entity.boss.dragon.EnderDragonEntity;
|
||||
import net.minecraft.entity.decoration.ArmorStandEntity;
|
||||
import net.minecraft.entity.decoration.ItemFrameEntity;
|
||||
import net.minecraft.entity.decoration.painting.PaintingEntity;
|
||||
import net.minecraft.entity.mob.AmbientEntity;
|
||||
import net.minecraft.entity.mob.MobEntity;
|
||||
import net.minecraft.entity.passive.AnimalEntity;
|
||||
import net.minecraft.entity.passive.TameableEntity;
|
||||
import net.minecraft.entity.passive.GolemEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.projectile.Projectile;
|
||||
import net.minecraft.entity.vehicle.AbstractMinecartEntity;
|
||||
import net.minecraft.entity.vehicle.BoatEntity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.village.Trader;
|
||||
|
||||
public class FabricEntityProperties implements EntityProperties {
|
||||
|
||||
private final Entity entity;
|
||||
|
||||
public FabricEntityProperties(Entity entity) {
|
||||
checkNotNull(entity);
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerDerived() {
|
||||
return entity instanceof PlayerEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isProjectile() {
|
||||
return entity instanceof EnderEyeEntity || entity instanceof Projectile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItem() {
|
||||
return entity instanceof ItemEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFallingBlock() {
|
||||
return entity instanceof FallingBlockEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPainting() {
|
||||
return entity instanceof PaintingEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemFrame() {
|
||||
return entity instanceof ItemFrameEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBoat() {
|
||||
return entity instanceof BoatEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMinecart() {
|
||||
return entity instanceof AbstractMinecartEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTNT() {
|
||||
return entity instanceof TntEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExperienceOrb() {
|
||||
return entity instanceof ExperienceOrbEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLiving() {
|
||||
return entity instanceof MobEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnimal() {
|
||||
return entity instanceof AnimalEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAmbient() {
|
||||
return entity instanceof AmbientEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNPC() {
|
||||
return entity instanceof Npc || entity instanceof Trader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGolem() {
|
||||
return entity instanceof GolemEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTamed() {
|
||||
return entity instanceof TameableEntity && ((TameableEntity) entity).isTamed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTagged() {
|
||||
return entity.hasCustomName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isArmorStand() {
|
||||
return entity instanceof ArmorStandEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPasteable() {
|
||||
return !(entity instanceof ServerPlayerEntity || entity instanceof EnderDragonEntity);
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import com.sk89q.worldedit.registry.Category;
|
||||
import com.sk89q.worldedit.world.item.ItemType;
|
||||
import com.sk89q.worldedit.world.registry.ItemCategoryRegistry;
|
||||
import net.minecraft.tag.ItemTags;
|
||||
import net.minecraft.tag.Tag;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class FabricItemCategoryRegistry implements ItemCategoryRegistry {
|
||||
@Override
|
||||
public Set<ItemType> getCategorisedByName(String category) {
|
||||
return Optional.ofNullable(ItemTags.getContainer().get(new Identifier(category)))
|
||||
.map(Tag::values).orElse(Collections.emptySet())
|
||||
.stream().map(FabricAdapter::adapt).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ItemType> getAll(Category<ItemType> category) {
|
||||
return getCategorisedByName(category.getId());
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import com.sk89q.worldedit.world.item.ItemType;
|
||||
import com.sk89q.worldedit.world.registry.BundledItemRegistry;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.client.resource.language.I18n;
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class FabricItemRegistry extends BundledItemRegistry {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName(ItemType itemType) {
|
||||
if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) {
|
||||
final Item item = FabricAdapter.adapt(itemType);
|
||||
return I18n.translate(item.getTranslationKey());
|
||||
}
|
||||
return super.getName(itemType);
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.world.GameMode;
|
||||
|
||||
public interface FabricPermissionsProvider {
|
||||
|
||||
boolean hasPermission(ServerPlayerEntity player, String permission);
|
||||
|
||||
void registerPermission(String permission);
|
||||
|
||||
class VanillaPermissionsProvider implements FabricPermissionsProvider {
|
||||
|
||||
private FabricPlatform platform;
|
||||
|
||||
public VanillaPermissionsProvider(FabricPlatform platform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(ServerPlayerEntity player, String permission) {
|
||||
FabricConfiguration configuration = platform.getConfiguration();
|
||||
return configuration.cheatMode ||
|
||||
player.server.getPlayerManager().isOperator(player.getGameProfile()) ||
|
||||
(configuration.creativeEnable && player.interactionManager.getGameMode() == GameMode.CREATIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPermission(String permission) {}
|
||||
}
|
||||
}
|
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import com.sk89q.worldedit.command.util.PermissionCondition;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.AbstractPlatform;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.extension.platform.MultiUserPlatform;
|
||||
import com.sk89q.worldedit.extension.platform.Preference;
|
||||
import com.sk89q.worldedit.world.DataFixer;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.registry.Registries;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.PlayerManager;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import org.enginehub.piston.Command;
|
||||
import org.enginehub.piston.CommandManager;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
class FabricPlatform extends AbstractPlatform implements MultiUserPlatform {
|
||||
|
||||
private final FabricWorldEdit mod;
|
||||
private final MinecraftServer server;
|
||||
private final FabricDataFixer dataFixer;
|
||||
private boolean hookingEvents = false;
|
||||
|
||||
FabricPlatform(FabricWorldEdit mod, MinecraftServer server) {
|
||||
this.mod = mod;
|
||||
this.server = server;
|
||||
this.dataFixer = new FabricDataFixer(getDataVersion());
|
||||
}
|
||||
|
||||
boolean isHookingEvents() {
|
||||
return hookingEvents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Registries getRegistries() {
|
||||
return FabricRegistries.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDataVersion() {
|
||||
return SharedConstants.getGameVersion().getWorldVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataFixer getDataFixer() {
|
||||
return dataFixer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidMobType(String type) {
|
||||
return Registry.ENTITY_TYPE.containsId(new Identifier(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
getConfiguration().load();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int schedule(long delay, long period, Runnable task) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends World> getWorlds() {
|
||||
Iterable<ServerWorld> worlds = server.getWorlds();
|
||||
List<World> ret = new ArrayList<>();
|
||||
for (ServerWorld world : worlds) {
|
||||
ret.add(new FabricWorld(world));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Player matchPlayer(Player player) {
|
||||
if (player instanceof FabricPlayer) {
|
||||
return player;
|
||||
} else {
|
||||
ServerPlayerEntity entity = server.getPlayerManager().getPlayer(player.getName());
|
||||
return entity != null ? new FabricPlayer(entity) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public World matchWorld(World world) {
|
||||
if (world instanceof FabricWorld) {
|
||||
return world;
|
||||
} else {
|
||||
for (ServerWorld ws : server.getWorlds()) {
|
||||
if (ws.getLevelProperties().getLevelName().equals(world.getName())) {
|
||||
return new FabricWorld(ws);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCommands(CommandManager manager) {
|
||||
if (server == null) return;
|
||||
net.minecraft.server.command.CommandManager mcMan = server.getCommandManager();
|
||||
|
||||
for (Command command : manager.getAllCommands().collect(toList())) {
|
||||
CommandWrapper.register(mcMan.getDispatcher(), command);
|
||||
Set<String> perms = command.getCondition().as(PermissionCondition.class)
|
||||
.map(PermissionCondition::getPermissions)
|
||||
.orElseGet(Collections::emptySet);
|
||||
if (!perms.isEmpty()) {
|
||||
perms.forEach(FabricWorldEdit.inst.getPermissionsProvider()::registerPermission);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerGameHooks() {
|
||||
// We registered the events already anyway, so we just 'turn them on'
|
||||
hookingEvents = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FabricConfiguration getConfiguration() {
|
||||
return mod.getConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return mod.getInternalVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformName() {
|
||||
return "Fabric-Official";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlatformVersion() {
|
||||
return mod.getInternalVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Capability, Preference> getCapabilities() {
|
||||
Map<Capability, Preference> capabilities = new EnumMap<>(Capability.class);
|
||||
capabilities.put(Capability.CONFIGURATION, Preference.PREFER_OTHERS);
|
||||
capabilities.put(Capability.WORLDEDIT_CUI, Preference.NORMAL);
|
||||
capabilities.put(Capability.GAME_HOOKS, Preference.NORMAL);
|
||||
capabilities.put(Capability.PERMISSIONS, Preference.NORMAL);
|
||||
capabilities.put(Capability.USER_COMMANDS, Preference.NORMAL);
|
||||
capabilities.put(Capability.WORLD_EDITING, Preference.PREFERRED);
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Actor> getConnectedUsers() {
|
||||
List<Actor> users = new ArrayList<>();
|
||||
PlayerManager scm = server.getPlayerManager();
|
||||
for (ServerPlayerEntity entity : scm.getPlayerList()) {
|
||||
if (entity != null) {
|
||||
users.add(new FabricPlayer(entity));
|
||||
}
|
||||
}
|
||||
return users;
|
||||
}
|
||||
}
|
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.util.StringUtil;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extension.platform.AbstractPlayerActor;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.fabric.net.handler.WECUIPacketHandler;
|
||||
import com.sk89q.worldedit.internal.cui.CUIEvent;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.session.SessionKey;
|
||||
import com.sk89q.worldedit.util.HandSide;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import com.sk89q.worldedit.util.formatting.text.serializer.gson.GsonComponentSerializer;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import net.minecraft.ChatFormat;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.network.packet.BlockEntityUpdateS2CPacket;
|
||||
import net.minecraft.client.network.packet.BlockUpdateS2CPacket;
|
||||
import net.minecraft.client.network.packet.CustomPayloadS2CPacket;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class FabricPlayer extends AbstractPlayerActor {
|
||||
|
||||
// see ClientPlayNetHandler: search for "invalid update packet", lots of hardcoded consts
|
||||
private static final int STRUCTURE_BLOCK_PACKET_ID = 7;
|
||||
private final ServerPlayerEntity player;
|
||||
|
||||
protected FabricPlayer(ServerPlayerEntity player) {
|
||||
this.player = player;
|
||||
ThreadSafeCache.getInstance().getOnlineIds().add(getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return player.getUuid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseItemStack getItemInHand(HandSide handSide) {
|
||||
ItemStack is = this.player.getStackInHand(handSide == HandSide.MAIN_HAND ? Hand.MAIN_HAND : Hand.OFF_HAND);
|
||||
return FabricAdapter.adapt(is);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.player.getName().getFormattedText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseEntity getState() {
|
||||
throw new UnsupportedOperationException("Cannot create a state from this object");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
Vector3 position = Vector3.at(this.player.x, this.player.y, this.player.z);
|
||||
return new Location(
|
||||
FabricWorldEdit.inst.getWorld(this.player.world),
|
||||
position,
|
||||
this.player.yaw,
|
||||
this.player.pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setLocation(Location location) {
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.sk89q.worldedit.world.World getWorld() {
|
||||
return FabricWorldEdit.inst.getWorld(this.player.world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveItem(BaseItemStack itemStack) {
|
||||
this.player.inventory.insertStack(FabricAdapter.adapt(itemStack));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchCUIEvent(CUIEvent event) {
|
||||
String[] params = event.getParameters();
|
||||
String send = event.getTypeId();
|
||||
if (params.length > 0) {
|
||||
send = send + "|" + StringUtil.joinString(params, "|");
|
||||
}
|
||||
PacketByteBuf buffer = new PacketByteBuf(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET)));
|
||||
CustomPayloadS2CPacket packet = new CustomPayloadS2CPacket(new Identifier(FabricWorldEdit.MOD_ID, FabricWorldEdit.CUI_PLUGIN_CHANNEL), buffer);
|
||||
this.player.networkHandler.sendPacket(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printRaw(String msg) {
|
||||
for (String part : msg.split("\n")) {
|
||||
this.player.sendMessage(new TextComponent(part));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printDebug(String msg) {
|
||||
sendColorized(msg, ChatFormat.GRAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String msg) {
|
||||
sendColorized(msg, ChatFormat.LIGHT_PURPLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printError(String msg) {
|
||||
sendColorized(msg, ChatFormat.RED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(Component component) {
|
||||
this.player.sendMessage(net.minecraft.network.chat.Component.Serializer.fromJsonString(GsonComponentSerializer.INSTANCE.serialize(component)));
|
||||
}
|
||||
|
||||
private void sendColorized(String msg, ChatFormat formatting) {
|
||||
for (String part : msg.split("\n")) {
|
||||
TextComponent component = new TextComponent(part);
|
||||
component.getStyle().setColor(formatting);
|
||||
this.player.sendMessage(component);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(Vector3 pos, float pitch, float yaw) {
|
||||
this.player.networkHandler.requestTeleport(pos.getX(), pos.getY(), pos.getZ(), yaw, pitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getGroups() {
|
||||
return new String[]{}; // WorldEditMod.inst.getPermissionsResolver().getGroups(this.player.username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBag getInventoryBlockBag() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String perm) {
|
||||
return FabricWorldEdit.inst.getPermissionsProvider().hasPermission(player, perm);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T getFacet(Class<? extends T> cls) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> void sendFakeBlock(BlockVector3 pos, B block) {
|
||||
World world = getWorld();
|
||||
if (!(world instanceof FabricWorld)) {
|
||||
return;
|
||||
}
|
||||
BlockPos loc = FabricAdapter.toBlockPos(pos);
|
||||
if (block == null) {
|
||||
final BlockUpdateS2CPacket packetOut = new BlockUpdateS2CPacket(((FabricWorld) world).getWorld(), loc);
|
||||
player.networkHandler.sendPacket(packetOut);
|
||||
} else {
|
||||
final BlockUpdateS2CPacket packetOut = new BlockUpdateS2CPacket();
|
||||
PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer());
|
||||
buf.writeBlockPos(loc);
|
||||
buf.writeVarInt(Block.getRawIdFromState(FabricAdapter.adapt(block.toImmutableState())));
|
||||
try {
|
||||
packetOut.read(buf);
|
||||
} catch (IOException e) {
|
||||
return;
|
||||
}
|
||||
player.networkHandler.sendPacket(packetOut);
|
||||
if (block instanceof BaseBlock && block.getBlockType().equals(BlockTypes.STRUCTURE_BLOCK)) {
|
||||
final BaseBlock baseBlock = (BaseBlock) block;
|
||||
final CompoundTag nbtData = baseBlock.getNbtData();
|
||||
if (nbtData != null) {
|
||||
player.networkHandler.sendPacket(new BlockEntityUpdateS2CPacket(
|
||||
new BlockPos(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()),
|
||||
STRUCTURE_BLOCK_PACKET_ID,
|
||||
NBTConverter.toNative(nbtData))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionKey getSessionKey() {
|
||||
return new SessionKeyImpl(player.getUuid(), player.getName().getString());
|
||||
}
|
||||
|
||||
private static class SessionKeyImpl implements SessionKey {
|
||||
// If not static, this will leak a reference
|
||||
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
private SessionKeyImpl(UUID uuid, String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUniqueId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
// We can't directly check if the player is online because
|
||||
// the list of players is not thread safe
|
||||
return ThreadSafeCache.getInstance().getOnlineIds().contains(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPersistent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import com.sk89q.worldedit.world.registry.BiomeRegistry;
|
||||
import com.sk89q.worldedit.world.registry.BlockCategoryRegistry;
|
||||
import com.sk89q.worldedit.world.registry.BlockRegistry;
|
||||
import com.sk89q.worldedit.world.registry.BundledRegistries;
|
||||
import com.sk89q.worldedit.world.registry.ItemCategoryRegistry;
|
||||
import com.sk89q.worldedit.world.registry.ItemRegistry;
|
||||
|
||||
/**
|
||||
* World data for the Fabric platform.
|
||||
*/
|
||||
class FabricRegistries extends BundledRegistries {
|
||||
|
||||
private static final FabricRegistries INSTANCE = new FabricRegistries();
|
||||
private final BlockRegistry blockRegistry = new FabricBlockRegistry();
|
||||
private final BiomeRegistry biomeRegistry = new FabricBiomeRegistry();
|
||||
private final ItemRegistry itemRegistry = new FabricItemRegistry();
|
||||
private final BlockCategoryRegistry blockCategoryRegistry = new FabricBlockCategoryRegistry();
|
||||
private final ItemCategoryRegistry itemCategoryRegistry = new FabricItemCategoryRegistry();
|
||||
|
||||
@Override
|
||||
public BlockRegistry getBlockRegistry() {
|
||||
return blockRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeRegistry getBiomeRegistry() {
|
||||
return biomeRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemRegistry getItemRegistry() {
|
||||
return itemRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockCategoryRegistry getBlockCategoryRegistry() {
|
||||
return blockCategoryRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemCategoryRegistry getItemCategoryRegistry() {
|
||||
return itemCategoryRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a static instance.
|
||||
*
|
||||
* @return an instance
|
||||
*/
|
||||
public static FabricRegistries getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,597 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.io.Files;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.internal.Constants;
|
||||
import com.sk89q.worldedit.internal.block.BlockStateIdAccess;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Direction;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
||||
import com.sk89q.worldedit.world.AbstractWorld;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.item.ItemTypes;
|
||||
import com.sk89q.worldedit.world.weather.WeatherType;
|
||||
import com.sk89q.worldedit.world.weather.WeatherTypes;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.LeavesBlock;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.entity.ItemEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemUsageContext;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.WorldGenerationProgressListener;
|
||||
import net.minecraft.server.world.ServerChunkManager;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Clearable;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldSaveHandler;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.ChunkManager;
|
||||
import net.minecraft.world.chunk.ChunkStatus;
|
||||
import net.minecraft.world.chunk.WorldChunk;
|
||||
import net.minecraft.world.gen.feature.BirchTreeFeature;
|
||||
import net.minecraft.world.gen.feature.DarkOakTreeFeature;
|
||||
import net.minecraft.world.gen.feature.DefaultFeatureConfig;
|
||||
import net.minecraft.world.gen.feature.Feature;
|
||||
import net.minecraft.world.gen.feature.FeatureConfig;
|
||||
import net.minecraft.world.gen.feature.HugeBrownMushroomFeature;
|
||||
import net.minecraft.world.gen.feature.HugeRedMushroomFeature;
|
||||
import net.minecraft.world.gen.feature.JungleGroundBushFeature;
|
||||
import net.minecraft.world.gen.feature.JungleTreeFeature;
|
||||
import net.minecraft.world.gen.feature.LargeOakTreeFeature;
|
||||
import net.minecraft.world.gen.feature.MegaJungleTreeFeature;
|
||||
import net.minecraft.world.gen.feature.MegaPineTreeFeature;
|
||||
import net.minecraft.world.gen.feature.OakTreeFeature;
|
||||
import net.minecraft.world.gen.feature.PineTreeFeature;
|
||||
import net.minecraft.world.gen.feature.PlantedFeatureConfig;
|
||||
import net.minecraft.world.gen.feature.SavannaTreeFeature;
|
||||
import net.minecraft.world.gen.feature.SpruceTreeFeature;
|
||||
import net.minecraft.world.gen.feature.SwampTreeFeature;
|
||||
import net.minecraft.world.level.LevelProperties;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* An adapter to Minecraft worlds for WorldEdit.
|
||||
*/
|
||||
public class FabricWorld extends AbstractWorld {
|
||||
|
||||
private static final Random random = new Random();
|
||||
private static final int UPDATE = 1, NOTIFY = 2;
|
||||
|
||||
private static final net.minecraft.block.BlockState JUNGLE_LOG = Blocks.JUNGLE_LOG.getDefaultState();
|
||||
private static final net.minecraft.block.BlockState JUNGLE_LEAF = Blocks.JUNGLE_LEAVES.getDefaultState().with(LeavesBlock.PERSISTENT, Boolean.TRUE);
|
||||
private static final net.minecraft.block.BlockState JUNGLE_SHRUB = Blocks.OAK_LEAVES.getDefaultState().with(LeavesBlock.PERSISTENT, Boolean.TRUE);
|
||||
|
||||
private final WeakReference<World> worldRef;
|
||||
|
||||
/**
|
||||
* Construct a new world.
|
||||
*
|
||||
* @param world the world
|
||||
*/
|
||||
FabricWorld(World world) {
|
||||
checkNotNull(world);
|
||||
this.worldRef = new WeakReference<>(world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the underlying handle to the world.
|
||||
*
|
||||
* @return the world
|
||||
* @throws WorldEditException thrown if a reference to the world was lost (i.e. world was unloaded)
|
||||
*/
|
||||
public World getWorldChecked() throws WorldEditException {
|
||||
World world = worldRef.get();
|
||||
if (world != null) {
|
||||
return world;
|
||||
} else {
|
||||
throw new WorldReferenceLostException("The reference to the world was lost (i.e. the world may have been unloaded)");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the underlying handle to the world.
|
||||
*
|
||||
* @return the world
|
||||
* @throws RuntimeException thrown if a reference to the world was lost (i.e. world was unloaded)
|
||||
*/
|
||||
public World getWorld() {
|
||||
World world = worldRef.get();
|
||||
if (world != null) {
|
||||
return world;
|
||||
} else {
|
||||
throw new RuntimeException("The reference to the world was lost (i.e. the world may have been unloaded)");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getWorld().getLevelProperties().getLevelName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getStoragePath() {
|
||||
final World world = getWorld();
|
||||
if (world instanceof ServerWorld) {
|
||||
return ((ServerWorld) world).getSaveHandler().getWorldDir().toPath();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, boolean notifyAndLight) throws WorldEditException {
|
||||
checkNotNull(position);
|
||||
checkNotNull(block);
|
||||
|
||||
World world = getWorldChecked();
|
||||
int x = position.getBlockX();
|
||||
int y = position.getBlockY();
|
||||
int z = position.getBlockZ();
|
||||
|
||||
// First set the block
|
||||
Chunk chunk = world.getChunk(x >> 4, z >> 4);
|
||||
BlockPos pos = new BlockPos(x, y, z);
|
||||
net.minecraft.block.BlockState old = chunk.getBlockState(pos);
|
||||
OptionalInt stateId = BlockStateIdAccess.getBlockStateId(block.toImmutableState());
|
||||
net.minecraft.block.BlockState newState = stateId.isPresent() ? Block.getStateFromRawId(stateId.getAsInt()) : FabricAdapter.adapt(block.toImmutableState());
|
||||
net.minecraft.block.BlockState successState = chunk.setBlockState(pos, newState, false);
|
||||
boolean successful = successState != null;
|
||||
|
||||
// Create the TileEntity
|
||||
if (successful || old == newState) {
|
||||
if (block instanceof BaseBlock) {
|
||||
CompoundTag tag = ((BaseBlock) block).getNbtData();
|
||||
if (tag != null) {
|
||||
net.minecraft.nbt.CompoundTag nativeTag = NBTConverter.toNative(tag);
|
||||
nativeTag.putString("id", ((BaseBlock) block).getNbtId());
|
||||
TileEntityUtils.setTileEntity(world, position, nativeTag);
|
||||
successful = true; // update if TE changed as well
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (successful && notifyAndLight) {
|
||||
world.getChunkManager().getLightingProvider().enqueueLightUpdate(pos);
|
||||
world.updateListeners(pos, old, newState, UPDATE | NOTIFY);
|
||||
}
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException {
|
||||
BlockPos pos = new BlockPos(position.getX(), position.getY(), position.getZ());
|
||||
getWorld().updateListeners(pos, FabricAdapter.adapt(previousType), getWorld().getBlockState(pos), 1 | 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockLightLevel(BlockVector3 position) {
|
||||
checkNotNull(position);
|
||||
return getWorld().getLightLevel(FabricAdapter.toBlockPos(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clearContainerBlockContents(BlockVector3 position) {
|
||||
checkNotNull(position);
|
||||
BlockEntity tile = getWorld().getBlockEntity(FabricAdapter.toBlockPos(position));
|
||||
if ((tile instanceof Clearable)) {
|
||||
((Clearable) tile).clear();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiome(BlockVector2 position) {
|
||||
checkNotNull(position);
|
||||
return FabricAdapter.adapt(getWorld().getBiome(new BlockPos(position.getBlockX(), 0, position.getBlockZ())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 position, BiomeType biome) {
|
||||
checkNotNull(position);
|
||||
checkNotNull(biome);
|
||||
|
||||
Chunk chunk = getWorld().getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4, ChunkStatus.FULL, false);
|
||||
if (chunk == null) {
|
||||
return false;
|
||||
}
|
||||
chunk.getBiomeArray()[((position.getBlockZ() & 0xF) << 4 | position.getBlockX() & 0xF)] = FabricAdapter.adapt(biome);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final LoadingCache<ServerWorld, WorldEditFakePlayer> fakePlayers
|
||||
= CacheBuilder.newBuilder().weakKeys().softValues().build(CacheLoader.from(WorldEditFakePlayer::new));
|
||||
|
||||
@Override
|
||||
public boolean useItem(BlockVector3 position, BaseItem item, Direction face) {
|
||||
ItemStack stack = FabricAdapter.adapt(new BaseItemStack(item.getType(), item.getNbtData(), 1));
|
||||
ServerWorld world = (ServerWorld) getWorld();
|
||||
final WorldEditFakePlayer fakePlayer;
|
||||
try {
|
||||
fakePlayer = fakePlayers.get(world);
|
||||
} catch (ExecutionException ignored) {
|
||||
return false;
|
||||
}
|
||||
fakePlayer.setStackInHand(Hand.MAIN_HAND, stack);
|
||||
fakePlayer.setPositionAndAngles(position.getBlockX(), position.getBlockY(), position.getBlockZ(),
|
||||
(float) face.toVector().toYaw(), (float) face.toVector().toPitch());
|
||||
final BlockPos blockPos = FabricAdapter.toBlockPos(position);
|
||||
final BlockHitResult rayTraceResult = new BlockHitResult(FabricAdapter.toVec3(position),
|
||||
FabricAdapter.adapt(face), blockPos, false);
|
||||
ItemUsageContext itemUseContext = new ItemUsageContext(fakePlayer, Hand.MAIN_HAND, rayTraceResult);
|
||||
ActionResult used = stack.useOnBlock(itemUseContext);
|
||||
if (used != ActionResult.SUCCESS) {
|
||||
// try activating the block
|
||||
if (getWorld().getBlockState(blockPos).activate(world, fakePlayer, Hand.MAIN_HAND, rayTraceResult)) {
|
||||
used = ActionResult.SUCCESS;
|
||||
} else {
|
||||
used = stack.getItem().use(world, fakePlayer, Hand.MAIN_HAND).getResult();
|
||||
}
|
||||
}
|
||||
return used == ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropItem(Vector3 position, BaseItemStack item) {
|
||||
checkNotNull(position);
|
||||
checkNotNull(item);
|
||||
|
||||
if (item.getType() == ItemTypes.AIR) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemEntity entity = new ItemEntity(getWorld(), position.getX(), position.getY(), position.getZ(), FabricAdapter.adapt(item));
|
||||
entity.setPickupDelay(10);
|
||||
getWorld().spawnEntity(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simulateBlockMine(BlockVector3 position) {
|
||||
BlockPos pos = FabricAdapter.toBlockPos(position);
|
||||
getWorld().breakBlock(pos, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerate(Region region, EditSession editSession) {
|
||||
// Don't even try to regen if it's going to fail.
|
||||
ChunkManager provider = getWorld().getChunkManager();
|
||||
if (!(provider instanceof ServerChunkManager)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
File saveFolder = Files.createTempDir();
|
||||
// register this just in case something goes wrong
|
||||
// normally it should be deleted at the end of this method
|
||||
saveFolder.deleteOnExit();
|
||||
try {
|
||||
ServerWorld originalWorld = (ServerWorld) getWorld();
|
||||
|
||||
MinecraftServer server = originalWorld.getServer();
|
||||
WorldSaveHandler saveHandler = new WorldSaveHandler(saveFolder, originalWorld.getSaveHandler().getWorldDir().getName(), server, server.getDataFixer());
|
||||
World freshWorld = new ServerWorld(server, server.getWorkerExecutor(), saveHandler, originalWorld.getLevelProperties(),
|
||||
originalWorld.dimension.getType(), originalWorld.getProfiler(), new NoOpChunkStatusListener());
|
||||
|
||||
// Pre-gen all the chunks
|
||||
// We need to also pull one more chunk in every direction
|
||||
CuboidRegion expandedPreGen = new CuboidRegion(region.getMinimumPoint().subtract(16, 0, 16), region.getMaximumPoint().add(16, 0, 16));
|
||||
for (BlockVector2 chunk : expandedPreGen.getChunks()) {
|
||||
freshWorld.getChunk(chunk.getBlockX(), chunk.getBlockZ());
|
||||
}
|
||||
|
||||
FabricWorld from = new FabricWorld(freshWorld);
|
||||
for (BlockVector3 vec : region) {
|
||||
editSession.setBlock(vec, from.getFullBlock(vec));
|
||||
}
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
saveFolder.delete();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Feature<? extends FeatureConfig> createTreeFeatureGenerator(TreeType type) {
|
||||
switch (type) {
|
||||
case TREE: return new OakTreeFeature(DefaultFeatureConfig::deserialize, true);
|
||||
case BIG_TREE: return new LargeOakTreeFeature(DefaultFeatureConfig::deserialize, true);
|
||||
case REDWOOD: return new PineTreeFeature(DefaultFeatureConfig::deserialize);
|
||||
case TALL_REDWOOD: return new SpruceTreeFeature(DefaultFeatureConfig::deserialize, true);
|
||||
case BIRCH: return new BirchTreeFeature(DefaultFeatureConfig::deserialize, true, false);
|
||||
case JUNGLE: return new MegaJungleTreeFeature(DefaultFeatureConfig::deserialize, true, 10, 20, JUNGLE_LOG, JUNGLE_LEAF);
|
||||
case SMALL_JUNGLE: return new JungleTreeFeature(DefaultFeatureConfig::deserialize, true, 4 + random.nextInt(7), JUNGLE_LOG, JUNGLE_LEAF, false);
|
||||
case SHORT_JUNGLE: return new JungleTreeFeature(DefaultFeatureConfig::deserialize, true, 4 + random.nextInt(7), JUNGLE_LOG, JUNGLE_LEAF, true);
|
||||
case JUNGLE_BUSH: return new JungleGroundBushFeature(DefaultFeatureConfig::deserialize, JUNGLE_LOG, JUNGLE_SHRUB);
|
||||
case SWAMP: return new SwampTreeFeature(DefaultFeatureConfig::deserialize);
|
||||
case ACACIA: return new SavannaTreeFeature(DefaultFeatureConfig::deserialize, true);
|
||||
case DARK_OAK: return new DarkOakTreeFeature(DefaultFeatureConfig::deserialize, true);
|
||||
case MEGA_REDWOOD: return new MegaPineTreeFeature(DefaultFeatureConfig::deserialize, true, random.nextBoolean());
|
||||
case TALL_BIRCH: return new BirchTreeFeature(DefaultFeatureConfig::deserialize, true, true);
|
||||
case RED_MUSHROOM: return new HugeRedMushroomFeature(PlantedFeatureConfig::deserialize);
|
||||
case BROWN_MUSHROOM: return new HugeBrownMushroomFeature(PlantedFeatureConfig::deserialize);
|
||||
case RANDOM: return createTreeFeatureGenerator(TreeType.values()[ThreadLocalRandom.current().nextInt(TreeType.values().length)]);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private FeatureConfig createFeatureConfig(TreeType type) {
|
||||
if (type == TreeType.RED_MUSHROOM || type == TreeType.BROWN_MUSHROOM) {
|
||||
return new PlantedFeatureConfig(true);
|
||||
} else {
|
||||
return new DefaultFeatureConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean generateTree(TreeType type, EditSession editSession, BlockVector3 position) throws MaxChangedBlocksException {
|
||||
@SuppressWarnings("unchecked")
|
||||
Feature<FeatureConfig> generator = (Feature<FeatureConfig>) createTreeFeatureGenerator(type);
|
||||
return generator != null
|
||||
&& generator.generate(getWorld(), getWorld().getChunkManager().getChunkGenerator(), random,
|
||||
FabricAdapter.toBlockPos(position), createFeatureConfig(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkLoadedChunk(BlockVector3 pt) {
|
||||
getWorld().getChunk(FabricAdapter.toBlockPos(pt));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixAfterFastMode(Iterable<BlockVector2> chunks) {
|
||||
fixLighting(chunks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixLighting(Iterable<BlockVector2> chunks) {
|
||||
World world = getWorld();
|
||||
for (BlockVector2 chunk : chunks) {
|
||||
world.getChunkManager().getLightingProvider().suppressLight(new ChunkPos(chunk.getBlockX(), chunk.getBlockZ()), true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playEffect(Vector3 position, int type, int data) {
|
||||
getWorld().playLevelEvent(type, FabricAdapter.toBlockPos(position.toBlockPoint()), data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeatherType getWeather() {
|
||||
LevelProperties info = getWorld().getLevelProperties();
|
||||
if (info.isThundering()) {
|
||||
return WeatherTypes.THUNDER_STORM;
|
||||
}
|
||||
if (info.isRaining()) {
|
||||
return WeatherTypes.RAIN;
|
||||
}
|
||||
return WeatherTypes.CLEAR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRemainingWeatherDuration() {
|
||||
LevelProperties info = getWorld().getLevelProperties();
|
||||
if (info.isThundering()) {
|
||||
return info.getThunderTime();
|
||||
}
|
||||
if (info.isRaining()) {
|
||||
return info.getRainTime();
|
||||
}
|
||||
return info.getClearWeatherTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWeather(WeatherType weatherType) {
|
||||
setWeather(weatherType, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWeather(WeatherType weatherType, long duration) {
|
||||
LevelProperties info = getWorld().getLevelProperties();
|
||||
if (weatherType == WeatherTypes.THUNDER_STORM) {
|
||||
info.setClearWeatherTime(0);
|
||||
info.setThundering(true);
|
||||
info.setThunderTime((int) duration);
|
||||
} else if (weatherType == WeatherTypes.RAIN) {
|
||||
info.setClearWeatherTime(0);
|
||||
info.setRaining(true);
|
||||
info.setRainTime((int) duration);
|
||||
} else if (weatherType == WeatherTypes.CLEAR) {
|
||||
info.setRaining(false);
|
||||
info.setThundering(false);
|
||||
info.setClearWeatherTime((int) duration);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxY() {
|
||||
return getWorld().getHeight() - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 getSpawnPosition() {
|
||||
return FabricAdapter.adapt(getWorld().getSpawnPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(BlockVector3 position) {
|
||||
net.minecraft.block.BlockState mcState = getWorld()
|
||||
.getChunk(position.getBlockX() >> 4, position.getBlockZ() >> 4)
|
||||
.getBlockState(FabricAdapter.toBlockPos(position));
|
||||
|
||||
BlockState matchingBlock = BlockStateIdAccess.getBlockStateById(Block.getRawIdFromState(mcState));
|
||||
if (matchingBlock != null) {
|
||||
return matchingBlock;
|
||||
}
|
||||
|
||||
return FabricAdapter.adapt(mcState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getFullBlock(BlockVector3 position) {
|
||||
BlockPos pos = new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ());
|
||||
// Avoid creation by using the CHECK mode -- if it's needed, it'll be re-created anyways
|
||||
BlockEntity tile = ((WorldChunk) getWorld().getChunk(pos)).getBlockEntity(pos, WorldChunk.CreationType.CHECK);
|
||||
|
||||
if (tile != null) {
|
||||
return getBlock(position).toBaseBlock(NBTConverter.fromNative(TileEntityUtils.copyNbtData(tile)));
|
||||
} else {
|
||||
return getBlock(position).toBaseBlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getWorld().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ((o instanceof FabricWorld)) {
|
||||
FabricWorld other = ((FabricWorld) o);
|
||||
World otherWorld = other.worldRef.get();
|
||||
World thisWorld = worldRef.get();
|
||||
return otherWorld != null && otherWorld.equals(thisWorld);
|
||||
} else if (o instanceof com.sk89q.worldedit.world.World) {
|
||||
return ((com.sk89q.worldedit.world.World) o).getName().equals(getName());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Entity> getEntities(Region region) {
|
||||
final World world = getWorld();
|
||||
if (!(world instanceof ServerWorld)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return ((ServerWorld) world).getEntities(null, entity -> true)
|
||||
.stream()
|
||||
.filter(e -> region.contains(FabricAdapter.adapt(e.getBlockPos())))
|
||||
.map(FabricEntity::new).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends Entity> getEntities() {
|
||||
final World world = getWorld();
|
||||
if (!(world instanceof ServerWorld)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return ((ServerWorld) world).getEntities(null, entity -> true)
|
||||
.stream()
|
||||
.map(FabricEntity::new)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Entity createEntity(Location location, BaseEntity entity) {
|
||||
World world = getWorld();
|
||||
final Optional<EntityType<?>> entityType = EntityType.get(entity.getType().getId());
|
||||
if (!entityType.isPresent()) return null;
|
||||
net.minecraft.entity.Entity createdEntity = entityType.get().create(world);
|
||||
if (createdEntity != null) {
|
||||
CompoundTag nativeTag = entity.getNbtData();
|
||||
if (nativeTag != null) {
|
||||
net.minecraft.nbt.CompoundTag tag = NBTConverter.toNative(entity.getNbtData());
|
||||
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
|
||||
tag.remove(name);
|
||||
}
|
||||
createdEntity.fromTag(tag);
|
||||
}
|
||||
|
||||
createdEntity.setPositionAndAngles(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
|
||||
world.spawnEntity(createdEntity);
|
||||
return new FabricEntity(createdEntity);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when the reference to the world is lost.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static final class WorldReferenceLostException extends WorldEditException {
|
||||
private WorldReferenceLostException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
private static class NoOpChunkStatusListener implements WorldGenerationProgressListener {
|
||||
@Override
|
||||
public void start(ChunkPos chunkPos) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunkStatus(ChunkPos chunkPos, @Nullable ChunkStatus chunkStatus) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,326 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.worldedit.fabric.FabricAdapter.adaptPlayer;
|
||||
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.fabric.net.handler.WECUIPacketHandler;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.block.BlockCategory;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import com.sk89q.worldedit.world.entity.EntityType;
|
||||
import com.sk89q.worldedit.world.item.ItemCategory;
|
||||
import com.sk89q.worldedit.world.item.ItemType;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
|
||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
|
||||
import net.fabricmc.fabric.api.event.player.UseItemCallback;
|
||||
import net.fabricmc.fabric.api.event.server.ServerStartCallback;
|
||||
import net.fabricmc.fabric.api.event.server.ServerStopCallback;
|
||||
import net.fabricmc.fabric.api.event.server.ServerTickCallback;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.fabricmc.loader.api.ModContainer;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.tag.BlockTags;
|
||||
import net.minecraft.tag.ItemTags;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* The Fabric implementation of WorldEdit.
|
||||
*/
|
||||
public class FabricWorldEdit implements ModInitializer {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
public static final String MOD_ID = "worldedit";
|
||||
public static final String CUI_PLUGIN_CHANNEL = "cui";
|
||||
|
||||
private FabricPermissionsProvider provider;
|
||||
|
||||
public static FabricWorldEdit inst;
|
||||
|
||||
private FabricPlatform platform;
|
||||
private FabricConfiguration config;
|
||||
private Path workingDir;
|
||||
|
||||
private ModContainer container;
|
||||
|
||||
public FabricWorldEdit() {
|
||||
inst = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
this.container = FabricLoader.getInstance().getModContainer("worldedit").orElseThrow(
|
||||
() -> new IllegalStateException("WorldEdit mod missing in Fabric")
|
||||
);
|
||||
|
||||
// Setup working directory
|
||||
workingDir = new File(FabricLoader.getInstance().getConfigDirectory(), "worldedit").toPath();
|
||||
if (!Files.exists(workingDir)) {
|
||||
try {
|
||||
Files.createDirectory(workingDir);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
WECUIPacketHandler.init();
|
||||
|
||||
ServerTickCallback.EVENT.register(ThreadSafeCache.getInstance());
|
||||
ServerStartCallback.EVENT.register(this::onStartServer);
|
||||
ServerStopCallback.EVENT.register(this::onStopServer);
|
||||
AttackBlockCallback.EVENT.register(this::onLeftClickBlock);
|
||||
UseBlockCallback.EVENT.register(this::onRightClickBlock);
|
||||
UseItemCallback.EVENT.register(this::onRightClickAir);
|
||||
LOGGER.info("WorldEdit for Fabric (version " + getInternalVersion() + ") is loaded");
|
||||
}
|
||||
|
||||
private void setupPlatform(MinecraftServer server) {
|
||||
this.platform = new FabricPlatform(this, server);
|
||||
|
||||
WorldEdit.getInstance().getPlatformManager().register(platform);
|
||||
|
||||
this.provider = new FabricPermissionsProvider.VanillaPermissionsProvider(platform);
|
||||
}
|
||||
|
||||
private void setupRegistries() {
|
||||
// Blocks
|
||||
for (Identifier name : Registry.BLOCK.getIds()) {
|
||||
if (BlockType.REGISTRY.get(name.toString()) == null) {
|
||||
BlockType.REGISTRY.register(name.toString(), new BlockType(name.toString(),
|
||||
input -> FabricAdapter.adapt(FabricAdapter.adapt(input.getBlockType()).getDefaultState())));
|
||||
}
|
||||
}
|
||||
// Items
|
||||
for (Identifier name : Registry.ITEM.getIds()) {
|
||||
if (ItemType.REGISTRY.get(name.toString()) == null) {
|
||||
ItemType.REGISTRY.register(name.toString(), new ItemType(name.toString()));
|
||||
}
|
||||
}
|
||||
// Entities
|
||||
for (Identifier name : Registry.ENTITY_TYPE.getIds()) {
|
||||
if (EntityType.REGISTRY.get(name.toString()) == null) {
|
||||
EntityType.REGISTRY.register(name.toString(), new EntityType(name.toString()));
|
||||
}
|
||||
}
|
||||
// Biomes
|
||||
for (Identifier name : Registry.BIOME.getIds()) {
|
||||
if (BiomeType.REGISTRY.get(name.toString()) == null) {
|
||||
BiomeType.REGISTRY.register(name.toString(), new BiomeType(name.toString()));
|
||||
}
|
||||
}
|
||||
// Tags
|
||||
for (Identifier name : BlockTags.getContainer().getKeys()) {
|
||||
if (BlockCategory.REGISTRY.get(name.toString()) == null) {
|
||||
BlockCategory.REGISTRY.register(name.toString(), new BlockCategory(name.toString()));
|
||||
}
|
||||
}
|
||||
for (Identifier name : ItemTags.getContainer().getKeys()) {
|
||||
if (ItemCategory.REGISTRY.get(name.toString()) == null) {
|
||||
ItemCategory.REGISTRY.register(name.toString(), new ItemCategory(name.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onStartServer(MinecraftServer minecraftServer) {
|
||||
setupPlatform(minecraftServer);
|
||||
setupRegistries();
|
||||
|
||||
config = new FabricConfiguration(this);
|
||||
config.load();
|
||||
WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent());
|
||||
}
|
||||
|
||||
private void onStopServer(MinecraftServer minecraftServer) {
|
||||
WorldEdit worldEdit = WorldEdit.getInstance();
|
||||
worldEdit.getSessionManager().unload();
|
||||
worldEdit.getPlatformManager().unregister(platform);
|
||||
}
|
||||
|
||||
private boolean shouldSkip() {
|
||||
if (platform == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !platform.isHookingEvents(); // We have to be told to catch these events
|
||||
}
|
||||
|
||||
private ActionResult onLeftClickBlock(PlayerEntity playerEntity, World world, Hand hand, BlockPos blockPos, Direction direction) {
|
||||
if (shouldSkip() || hand == Hand.OFF_HAND || world.isClient) {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
WorldEdit we = WorldEdit.getInstance();
|
||||
FabricPlayer player = adaptPlayer((ServerPlayerEntity) playerEntity);
|
||||
FabricWorld localWorld = getWorld(world);
|
||||
Location pos = new Location(localWorld,
|
||||
blockPos.getX(),
|
||||
blockPos.getY(),
|
||||
blockPos.getZ()
|
||||
);
|
||||
|
||||
if (we.handleBlockLeftClick(player, pos)) {
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
if (we.handleArmSwing(player)) {
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
public void onLeftClickAir(PlayerEntity playerEntity, World world, Hand hand) {
|
||||
WorldEdit we = WorldEdit.getInstance();
|
||||
FabricPlayer player = adaptPlayer((ServerPlayerEntity) playerEntity);
|
||||
we.handleArmSwing(player);
|
||||
}
|
||||
|
||||
private ActionResult onRightClickBlock(PlayerEntity playerEntity, World world, Hand hand, BlockHitResult blockHitResult) {
|
||||
if (shouldSkip() || hand == Hand.OFF_HAND || world.isClient) {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
WorldEdit we = WorldEdit.getInstance();
|
||||
FabricPlayer player = adaptPlayer((ServerPlayerEntity) playerEntity);
|
||||
FabricWorld localWorld = getWorld(world);
|
||||
Location pos = new Location(localWorld,
|
||||
blockHitResult.getBlockPos().getX(),
|
||||
blockHitResult.getBlockPos().getY(),
|
||||
blockHitResult.getBlockPos().getZ()
|
||||
);
|
||||
|
||||
if (we.handleBlockRightClick(player, pos)) {
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
if (we.handleRightClick(player)) {
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
private ActionResult onRightClickAir(PlayerEntity playerEntity, World world, Hand hand) {
|
||||
if (shouldSkip() || hand == Hand.OFF_HAND || world.isClient) {
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
WorldEdit we = WorldEdit.getInstance();
|
||||
FabricPlayer player = adaptPlayer((ServerPlayerEntity) playerEntity);
|
||||
|
||||
if (we.handleRightClick(player)) {
|
||||
return ActionResult.SUCCESS;
|
||||
}
|
||||
|
||||
return ActionResult.PASS;
|
||||
}
|
||||
|
||||
// TODO Pass empty left click to server
|
||||
|
||||
/**
|
||||
* Get the configuration.
|
||||
*
|
||||
* @return the Fabric configuration
|
||||
*/
|
||||
FabricConfiguration getConfig() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the session for a player.
|
||||
*
|
||||
* @param player the player
|
||||
* @return the session
|
||||
*/
|
||||
public LocalSession getSession(ServerPlayerEntity player) {
|
||||
checkNotNull(player);
|
||||
return WorldEdit.getInstance().getSessionManager().get(adaptPlayer(player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WorldEdit proxy for the given world.
|
||||
*
|
||||
* @param world the world
|
||||
* @return the WorldEdit world
|
||||
*/
|
||||
public FabricWorld getWorld(World world) {
|
||||
checkNotNull(world);
|
||||
return new FabricWorld(world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WorldEdit proxy for the platform.
|
||||
*
|
||||
* @return the WorldEdit platform
|
||||
*/
|
||||
public Platform getPlatform() {
|
||||
return this.platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the working directory where WorldEdit's files are stored.
|
||||
*
|
||||
* @return the working directory
|
||||
*/
|
||||
public File getWorkingDir() {
|
||||
return this.workingDir.toFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version of the WorldEdit-Fabric implementation.
|
||||
*
|
||||
* @return a version string
|
||||
*/
|
||||
String getInternalVersion() {
|
||||
return container.getMetadata().getVersion().getFriendlyString();
|
||||
}
|
||||
|
||||
public void setPermissionsProvider(FabricPermissionsProvider provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public FabricPermissionsProvider getPermissionsProvider() {
|
||||
return provider;
|
||||
}
|
||||
}
|
@ -0,0 +1,252 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import com.sk89q.jnbt.ByteArrayTag;
|
||||
import com.sk89q.jnbt.ByteTag;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.DoubleTag;
|
||||
import com.sk89q.jnbt.EndTag;
|
||||
import com.sk89q.jnbt.FloatTag;
|
||||
import com.sk89q.jnbt.IntArrayTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.LongTag;
|
||||
import com.sk89q.jnbt.ShortTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Converts between JNBT and Minecraft NBT classes.
|
||||
*/
|
||||
final class NBTConverter {
|
||||
|
||||
private NBTConverter() {
|
||||
}
|
||||
|
||||
public static net.minecraft.nbt.Tag toNative(Tag tag) {
|
||||
if (tag instanceof IntArrayTag) {
|
||||
return toNative((IntArrayTag) tag);
|
||||
|
||||
} else if (tag instanceof ListTag) {
|
||||
return toNative((ListTag) tag);
|
||||
|
||||
} else if (tag instanceof LongTag) {
|
||||
return toNative((LongTag) tag);
|
||||
|
||||
} else if (tag instanceof StringTag) {
|
||||
return toNative((StringTag) tag);
|
||||
|
||||
} else if (tag instanceof IntTag) {
|
||||
return toNative((IntTag) tag);
|
||||
|
||||
} else if (tag instanceof ByteTag) {
|
||||
return toNative((ByteTag) tag);
|
||||
|
||||
} else if (tag instanceof ByteArrayTag) {
|
||||
return toNative((ByteArrayTag) tag);
|
||||
|
||||
} else if (tag instanceof CompoundTag) {
|
||||
return toNative((CompoundTag) tag);
|
||||
|
||||
} else if (tag instanceof FloatTag) {
|
||||
return toNative((FloatTag) tag);
|
||||
|
||||
} else if (tag instanceof ShortTag) {
|
||||
return toNative((ShortTag) tag);
|
||||
|
||||
} else if (tag instanceof DoubleTag) {
|
||||
return toNative((DoubleTag) tag);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Can't convert tag of type " + tag.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
public static net.minecraft.nbt.IntArrayTag toNative(IntArrayTag tag) {
|
||||
int[] value = tag.getValue();
|
||||
return new net.minecraft.nbt.IntArrayTag(Arrays.copyOf(value, value.length));
|
||||
}
|
||||
|
||||
public static net.minecraft.nbt.ListTag toNative(ListTag tag) {
|
||||
net.minecraft.nbt.ListTag list = new net.minecraft.nbt.ListTag();
|
||||
for (Tag child : tag.getValue()) {
|
||||
if (child instanceof EndTag) {
|
||||
continue;
|
||||
}
|
||||
list.add(toNative(child));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static net.minecraft.nbt.LongTag toNative(LongTag tag) {
|
||||
return new net.minecraft.nbt.LongTag(tag.getValue());
|
||||
}
|
||||
|
||||
public static net.minecraft.nbt.StringTag toNative(StringTag tag) {
|
||||
return new net.minecraft.nbt.StringTag(tag.getValue());
|
||||
}
|
||||
|
||||
public static net.minecraft.nbt.IntTag toNative(IntTag tag) {
|
||||
return new net.minecraft.nbt.IntTag(tag.getValue());
|
||||
}
|
||||
|
||||
public static net.minecraft.nbt.ByteTag toNative(ByteTag tag) {
|
||||
return new net.minecraft.nbt.ByteTag(tag.getValue());
|
||||
}
|
||||
|
||||
public static net.minecraft.nbt.ByteArrayTag toNative(ByteArrayTag tag) {
|
||||
byte[] value = tag.getValue();
|
||||
return new net.minecraft.nbt.ByteArrayTag(Arrays.copyOf(value, value.length));
|
||||
}
|
||||
|
||||
public static net.minecraft.nbt.CompoundTag toNative(CompoundTag tag) {
|
||||
net.minecraft.nbt.CompoundTag compound = new net.minecraft.nbt.CompoundTag();
|
||||
for (Entry<String, Tag> child : tag.getValue().entrySet()) {
|
||||
compound.put(child.getKey(), toNative(child.getValue()));
|
||||
}
|
||||
return compound;
|
||||
}
|
||||
|
||||
public static net.minecraft.nbt.FloatTag toNative(FloatTag tag) {
|
||||
return new net.minecraft.nbt.FloatTag(tag.getValue());
|
||||
}
|
||||
|
||||
public static net.minecraft.nbt.ShortTag toNative(ShortTag tag) {
|
||||
return new net.minecraft.nbt.ShortTag(tag.getValue());
|
||||
}
|
||||
|
||||
public static net.minecraft.nbt.DoubleTag toNative(DoubleTag tag) {
|
||||
return new net.minecraft.nbt.DoubleTag(tag.getValue());
|
||||
}
|
||||
|
||||
public static Tag fromNative(net.minecraft.nbt.Tag other) {
|
||||
if (other instanceof net.minecraft.nbt.IntArrayTag) {
|
||||
return fromNative((net.minecraft.nbt.IntArrayTag) other);
|
||||
|
||||
} else if (other instanceof net.minecraft.nbt.ListTag) {
|
||||
return fromNative((net.minecraft.nbt.ListTag) other);
|
||||
|
||||
} else if (other instanceof net.minecraft.nbt.EndTag) {
|
||||
return fromNative((net.minecraft.nbt.EndTag) other);
|
||||
|
||||
} else if (other instanceof net.minecraft.nbt.LongTag) {
|
||||
return fromNative((net.minecraft.nbt.LongTag) other);
|
||||
|
||||
} else if (other instanceof net.minecraft.nbt.StringTag) {
|
||||
return fromNative((net.minecraft.nbt.StringTag) other);
|
||||
|
||||
} else if (other instanceof net.minecraft.nbt.IntTag) {
|
||||
return fromNative((net.minecraft.nbt.IntTag) other);
|
||||
|
||||
} else if (other instanceof net.minecraft.nbt.ByteTag) {
|
||||
return fromNative((net.minecraft.nbt.ByteTag) other);
|
||||
|
||||
} else if (other instanceof net.minecraft.nbt.ByteArrayTag) {
|
||||
return fromNative((net.minecraft.nbt.ByteArrayTag) other);
|
||||
|
||||
} else if (other instanceof net.minecraft.nbt.CompoundTag) {
|
||||
return fromNative((net.minecraft.nbt.CompoundTag) other);
|
||||
|
||||
} else if (other instanceof net.minecraft.nbt.FloatTag) {
|
||||
return fromNative((net.minecraft.nbt.FloatTag) other);
|
||||
|
||||
} else if (other instanceof net.minecraft.nbt.ShortTag) {
|
||||
return fromNative((net.minecraft.nbt.ShortTag) other);
|
||||
|
||||
} else if (other instanceof net.minecraft.nbt.DoubleTag) {
|
||||
return fromNative((net.minecraft.nbt.DoubleTag) other);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Can't convert other of type " + other.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
public static IntArrayTag fromNative(net.minecraft.nbt.IntArrayTag other) {
|
||||
int[] value = other.getIntArray();
|
||||
return new IntArrayTag(Arrays.copyOf(value, value.length));
|
||||
}
|
||||
|
||||
public static ListTag fromNative(net.minecraft.nbt.ListTag other) {
|
||||
other = (net.minecraft.nbt.ListTag) other.copy();
|
||||
List<Tag> list = new ArrayList<>();
|
||||
Class<? extends Tag> listClass = StringTag.class;
|
||||
int tags = other.size();
|
||||
for (int i = 0; i < tags; i++) {
|
||||
Tag child = fromNative(other.remove(0));
|
||||
list.add(child);
|
||||
listClass = child.getClass();
|
||||
}
|
||||
return new ListTag(listClass, list);
|
||||
}
|
||||
|
||||
public static EndTag fromNative(net.minecraft.nbt.EndTag other) {
|
||||
return new EndTag();
|
||||
}
|
||||
|
||||
public static LongTag fromNative(net.minecraft.nbt.LongTag other) {
|
||||
return new LongTag(other.getLong());
|
||||
}
|
||||
|
||||
public static StringTag fromNative(net.minecraft.nbt.StringTag other) {
|
||||
return new StringTag(other.asString());
|
||||
}
|
||||
|
||||
public static IntTag fromNative(net.minecraft.nbt.IntTag other) {
|
||||
return new IntTag(other.getInt());
|
||||
}
|
||||
|
||||
public static ByteTag fromNative(net.minecraft.nbt.ByteTag other) {
|
||||
return new ByteTag(other.getByte());
|
||||
}
|
||||
|
||||
public static ByteArrayTag fromNative(net.minecraft.nbt.ByteArrayTag other) {
|
||||
byte[] value = other.getByteArray();
|
||||
return new ByteArrayTag(Arrays.copyOf(value, value.length));
|
||||
}
|
||||
|
||||
public static CompoundTag fromNative(net.minecraft.nbt.CompoundTag other) {
|
||||
Set<String> tags = other.getKeys();
|
||||
Map<String, Tag> map = new HashMap<>();
|
||||
for (String tagName : tags) {
|
||||
map.put(tagName, fromNative(other.getTag(tagName)));
|
||||
}
|
||||
return new CompoundTag(map);
|
||||
}
|
||||
|
||||
public static FloatTag fromNative(net.minecraft.nbt.FloatTag other) {
|
||||
return new FloatTag(other.getFloat());
|
||||
}
|
||||
|
||||
public static ShortTag fromNative(net.minecraft.nbt.ShortTag other) {
|
||||
return new ShortTag(other.getShort());
|
||||
}
|
||||
|
||||
public static DoubleTag fromNative(net.minecraft.nbt.DoubleTag other) {
|
||||
return new DoubleTag(other.getDouble());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.sk89q.worldedit.registry.state.Property;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
class PropertyAdapter<T extends Comparable<T>> implements Property<T> {
|
||||
|
||||
private final net.minecraft.state.property.Property<T> property;
|
||||
private final List<T> values;
|
||||
|
||||
public PropertyAdapter(net.minecraft.state.property.Property<T> property) {
|
||||
this.property = property;
|
||||
this.values = ImmutableList.copyOf(property.getValues());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return property.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getValueFor(String string) throws IllegalArgumentException {
|
||||
Optional<T> val = property.getValue(string);
|
||||
checkArgument(val.isPresent(), "%s has no value for %s", getName(), string);
|
||||
return val.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getName().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof Property)) {
|
||||
return false;
|
||||
}
|
||||
return getName().equals(((Property<?>) obj).getName());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import net.fabricmc.fabric.api.event.server.ServerTickCallback;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* Caches data that cannot be accessed from another thread safely.
|
||||
*/
|
||||
public class ThreadSafeCache implements ServerTickCallback {
|
||||
|
||||
private static final long REFRESH_DELAY = 1000 * 30;
|
||||
private static final ThreadSafeCache INSTANCE = new ThreadSafeCache();
|
||||
private Set<UUID> onlineIds = Collections.emptySet();
|
||||
private long lastRefresh = 0;
|
||||
|
||||
/**
|
||||
* Get an concurrent-safe set of UUIDs of online players.
|
||||
*
|
||||
* @return a set of UUIDs
|
||||
*/
|
||||
public Set<UUID> getOnlineIds() {
|
||||
return onlineIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(MinecraftServer server) {
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
if (now - lastRefresh > REFRESH_DELAY) {
|
||||
Set<UUID> onlineIds = new HashSet<>();
|
||||
|
||||
if (server == null) {
|
||||
return;
|
||||
}
|
||||
for (ServerPlayerEntity player : server.getPlayerManager().getPlayerList()) {
|
||||
if (player != null) {
|
||||
onlineIds.add(player.getUuid());
|
||||
}
|
||||
}
|
||||
|
||||
this.onlineIds = new CopyOnWriteArraySet<>(onlineIds);
|
||||
|
||||
lastRefresh = now;
|
||||
}
|
||||
}
|
||||
|
||||
public static ThreadSafeCache getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.IntTag;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Utility methods for setting tile entities in the world.
|
||||
*/
|
||||
final class TileEntityUtils {
|
||||
|
||||
private TileEntityUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given tag compound with position information.
|
||||
*
|
||||
* @param tag the tag
|
||||
* @param position the position
|
||||
*/
|
||||
private static void updateForSet(CompoundTag tag, BlockVector3 position) {
|
||||
checkNotNull(tag);
|
||||
checkNotNull(position);
|
||||
|
||||
tag.put("x", new IntTag(position.getBlockX()));
|
||||
tag.put("y", new IntTag(position.getBlockY()));
|
||||
tag.put("z", new IntTag(position.getBlockZ()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a tile entity at the given location using the tile entity ID from
|
||||
* the tag.
|
||||
*
|
||||
* @param world the world
|
||||
* @param position the position
|
||||
* @param tag the tag for the tile entity (may be null to do nothing)
|
||||
*/
|
||||
static void setTileEntity(World world, BlockVector3 position, @Nullable CompoundTag tag) {
|
||||
if (tag != null) {
|
||||
updateForSet(tag, position);
|
||||
BlockEntity tileEntity = BlockEntity.createFromTag(tag);
|
||||
if (tileEntity != null) {
|
||||
world.setBlockEntity(new BlockPos(position.getBlockX(), position.getBlockY(), position.getBlockZ()), tileEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static CompoundTag copyNbtData(BlockEntity tile) {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tile.toTag(tag);
|
||||
return tag;
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.network.ServerPlayerInteractionManager;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.stat.Stat;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class WorldEditFakePlayer extends ServerPlayerEntity {
|
||||
private static final GameProfile FAKE_WORLDEDIT_PROFILE = new GameProfile(UUID.nameUUIDFromBytes("worldedit".getBytes()), "[WorldEdit]");
|
||||
|
||||
public WorldEditFakePlayer(ServerWorld world) {
|
||||
super(world.getServer(), world, FAKE_WORLDEDIT_PROFILE, new ServerPlayerInteractionManager(world));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increaseStat(Stat<?> stat, int incrementer) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementStat(Stat<?> stat) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(Component component) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addChatMessage(Component component, boolean opt) {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Entity changeDimension(DimensionType dimensionType) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInvulnerableTo(DamageSource damageSource) {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric.mixin;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.sk89q.worldedit.fabric.FabricWorldEdit;
|
||||
import net.minecraft.container.ContainerListener;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ServerPlayerEntity.class)
|
||||
public abstract class MixinServerPlayerEntity extends PlayerEntity implements ContainerListener {
|
||||
|
||||
public MixinServerPlayerEntity(World world, GameProfile gameProfile) {
|
||||
super(world, gameProfile);
|
||||
}
|
||||
|
||||
@Inject(method = "swingHand", at = @At(value = "HEAD"))
|
||||
public void onSwing(Hand hand, CallbackInfo injectionInfo) {
|
||||
FabricWorldEdit.inst.onLeftClickAir(this, this.world, hand);
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.fabric.net.handler;
|
||||
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.fabric.FabricAdapter;
|
||||
import com.sk89q.worldedit.fabric.FabricPlayer;
|
||||
import com.sk89q.worldedit.fabric.FabricWorldEdit;
|
||||
import net.fabricmc.fabric.api.network.PacketConsumer;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.fabricmc.fabric.api.network.ServerSidePacketRegistry;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.network.packet.CustomPayloadS2CPacket;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.network.packet.CustomPayloadC2SPacket;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.PacketByteBuf;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public final class WECUIPacketHandler {
|
||||
private WECUIPacketHandler() {
|
||||
}
|
||||
|
||||
public static final Charset UTF_8_CHARSET = StandardCharsets.UTF_8;
|
||||
private static final Identifier CUI_IDENTIFIER = new Identifier(FabricWorldEdit.MOD_ID, FabricWorldEdit.CUI_PLUGIN_CHANNEL);
|
||||
|
||||
public static void init() {
|
||||
ServerSidePacketRegistry.INSTANCE.register(CUI_IDENTIFIER, (packetContext, packetByteBuf) -> {
|
||||
ServerPlayerEntity player = (ServerPlayerEntity) packetContext.getPlayer();
|
||||
LocalSession session = FabricWorldEdit.inst.getSession(player);
|
||||
|
||||
if (session.hasCUISupport()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String text = packetByteBuf.toString(UTF_8_CHARSET);
|
||||
final FabricPlayer actor = FabricAdapter.adaptPlayer(player);
|
||||
session.handleCUIInitializationMessage(text, actor);
|
||||
session.describeCUI(actor);
|
||||
});
|
||||
}
|
||||
}
|
BIN
worldedit-fabric/src/main/resources/assets/worldedit/icon.png
Normal file
BIN
worldedit-fabric/src/main/resources/assets/worldedit/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
@ -0,0 +1,33 @@
|
||||
#Don't put comments; they get removed
|
||||
default-max-polygon-points=-1
|
||||
schematic-save-dir=schematics
|
||||
super-pickaxe-many-drop-items=true
|
||||
register-help=true
|
||||
nav-wand-item=minecraft:compass
|
||||
profile=false
|
||||
trace-unflushed-sessions=false
|
||||
super-pickaxe-drop-items=true
|
||||
disallowed-blocks=minecraft:oak_sapling,minecraft:jungle_sapling,minecraft:dark_oak_sapling,minecraft:spruce_sapling,minecraft:birch_sapling,minecraft:acacia_sapling,minecraft:black_bed,minecraft:blue_bed,minecraft:brown_bed,minecraft:cyan_bed,minecraft:gray_bed,minecraft:green_bed,minecraft:light_blue_bed,minecraft:light_gray_bed,minecraft:lime_bed,minecraft:magenta_bed,minecraft:orange_bed,minecraft:pink_bed,minecraft:purple_bed,minecraft:red_bed,minecraft:white_bed,minecraft:yellow_bed,minecraft:powered_rail,minecraft:detector_rail,minecraft:grass,minecraft:dead_bush,minecraft:moving_piston,minecraft:piston_head,minecraft:sunflower,minecraft:rose_bush,minecraft:dandelion,minecraft:poppy,minecraft:brown_mushroom,minecraft:red_mushroom,minecraft:tnt,minecraft:torch,minecraft:fire,minecraft:redstone_wire,minecraft:wheat,minecraft:potatoes,minecraft:carrots,minecraft:melon_stem,minecraft:pumpkin_stem,minecraft:beetroots,minecraft:rail,minecraft:lever,minecraft:redstone_torch,minecraft:redstone_wall_torch,minecraft:repeater,minecraft:comparator,minecraft:stone_button,minecraft:birch_button,minecraft:acacia_button,minecraft:dark_oak_button,minecraft:jungle_button,minecraft:oak_button,minecraft:spruce_button,minecraft:cactus,minecraft:sugar_cane,minecraft:bedrock
|
||||
max-super-pickaxe-size=5
|
||||
max-brush-radius=10
|
||||
craftscript-dir=craftscripts
|
||||
no-double-slash=false
|
||||
wand-item=minecraft:wooden_axe
|
||||
shell-save-type=
|
||||
scripting-timeout=3000
|
||||
snapshots-dir=
|
||||
use-inventory-creative-override=false
|
||||
log-file=worldedit.log
|
||||
log-format=[%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s]: %5$s%6$s%n
|
||||
max-changed-blocks=-1
|
||||
nav-wand-distance=50
|
||||
butcher-default-radius=-1
|
||||
default-max-changed-blocks=-1
|
||||
history-size=15
|
||||
use-inventory=false
|
||||
allow-symbolic-links=false
|
||||
use-inventory-override=false
|
||||
log-commands=false
|
||||
butcher-max-radius=-1
|
||||
max-polygon-points=20
|
||||
max-radius=-1
|
37
worldedit-fabric/src/main/resources/fabric.mod.json
Normal file
37
worldedit-fabric/src/main/resources/fabric.mod.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "worldedit",
|
||||
"version": "${version}",
|
||||
|
||||
"name": "WorldEdit",
|
||||
"description": "WorldEdit is an easy-to-use in-game world editor for Minecraft, supporting both single- and multi-player.",
|
||||
"authors": [
|
||||
"sk89q",
|
||||
"wizjany",
|
||||
"TomyLobo",
|
||||
"kenzierocks",
|
||||
"Me4502"
|
||||
],
|
||||
"contact": {
|
||||
"homepage": "https://enginehub.org/worldedit/",
|
||||
"sources": "https://github.com/EngineHub/WorldEdit"
|
||||
},
|
||||
|
||||
"license": "GPL3",
|
||||
"icon": "assets/worldedit/icon.png",
|
||||
|
||||
"environment": "*",
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"com.sk89q.worldedit.fabric.FabricWorldEdit"
|
||||
]
|
||||
},
|
||||
|
||||
"depends": {
|
||||
"fabricloader": ">=0.4.0",
|
||||
"fabric": "*"
|
||||
},
|
||||
"mixins": [
|
||||
"worldedit.mixins.json"
|
||||
]
|
||||
}
|
6
worldedit-fabric/src/main/resources/pack.mcmeta
Normal file
6
worldedit-fabric/src/main/resources/pack.mcmeta
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "WorldEdit Resources",
|
||||
"pack_format": 4
|
||||
}
|
||||
}
|
13
worldedit-fabric/src/main/resources/worldedit.mixins.json
Normal file
13
worldedit-fabric/src/main/resources/worldedit.mixins.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "com.sk89q.worldedit.fabric.mixin",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [
|
||||
"MixinServerPlayerEntity"
|
||||
],
|
||||
"server": [
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
@ -124,7 +124,7 @@ public class ForgePlayer extends AbstractPlayerActor {
|
||||
send = send + "|" + StringUtil.joinString(params, "|");
|
||||
}
|
||||
PacketBuffer buffer = new PacketBuffer(Unpooled.copiedBuffer(send.getBytes(WECUIPacketHandler.UTF_8_CHARSET)));
|
||||
SCustomPayloadPlayPacket packet = new SCustomPayloadPlayPacket(new ResourceLocation(ForgeWorldEdit.CUI_PLUGIN_CHANNEL), buffer);
|
||||
SCustomPayloadPlayPacket packet = new SCustomPayloadPlayPacket(new ResourceLocation(ForgeWorldEdit.MOD_ID, ForgeWorldEdit.CUI_PLUGIN_CHANNEL), buffer);
|
||||
this.player.connection.sendPacket(packet);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user