Skip to content

Commit

Permalink
Place command (currently unfinished)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pedro270707 committed Sep 28, 2023
1 parent f90d2ad commit 58b9e4e
Show file tree
Hide file tree
Showing 12 changed files with 262 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/main/java/net/pedroricardo/commander/Commander.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ public class Commander implements ModInitializer {
public void onInitialize() {
LOGGER.info("Commander initialized.");
CommanderCommandManager.init();
CommanderHelper.init();
}
}
16 changes: 16 additions & 0 deletions src/main/java/net/pedroricardo/commander/CommanderHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
import com.mojang.brigadier.suggestion.Suggestion;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.fabricmc.loader.impl.launch.knot.Knot;
import net.minecraft.core.entity.Entity;
import net.minecraft.core.entity.EntityDispatcher;
import net.minecraft.core.entity.EntityLiving;
import net.minecraft.core.net.command.Command;
import net.minecraft.core.net.command.Commands;
import net.minecraft.core.util.helper.LogPrintStream;
import net.minecraft.core.util.helper.ReflectionHelper;
import net.minecraft.core.world.generate.feature.WorldFeature;
import net.pedroricardo.commander.content.CommanderCommandManager;

import java.awt.event.KeyEvent;
Expand All @@ -19,6 +22,8 @@
import java.util.function.Function;

public class CommanderHelper {
public static final Map<String, Class<? extends WorldFeature>> WORLD_FEATURES = new HashMap<>();

private static Collection<Integer> IGNORABLE_KEYS = Arrays.asList(
KeyEvent.VK_SHIFT,
KeyEvent.VK_CONTROL,
Expand Down Expand Up @@ -129,4 +134,15 @@ public static String getEntityName(Entity entity) {
}
return EntityDispatcher.getEntityString(entity);
}

public static void init() {
try {
for (Class<?> clazz : CommanderReflectionHelper.getAllClasses(className -> className.startsWith("net.minecraft.core.world.generate.feature"))) {
if (!WorldFeature.class.isAssignableFrom(clazz)) continue;
WORLD_FEATURES.put(clazz.getSimpleName().substring(12), (Class<? extends WorldFeature>) clazz);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package net.pedroricardo.commander;

import com.b100.utils.FileUtils;
import com.b100.utils.interfaces.Condition;
import net.fabricmc.loader.impl.launch.knot.Knot;
import net.minecraft.core.util.helper.ReflectionHelper;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class CommanderReflectionHelper {
public static List<Class<?>> getAllClasses(Condition<String> classNameCondition) {
String[] classPathEntries;
ArrayList classes = new ArrayList();
for (String classPathEntry : classPathEntries = System.getProperty("java.class.path").split(";")) {
File file = new File(classPathEntry);
if (file.isDirectory()) {
int l = file.getAbsolutePath().length() + 1;
List<File> files = FileUtils.getAllFiles(file);
for (File file2 : files) {
if (!file2.getName().endsWith(".class")) continue;
tryAddClass(classes, file2.getAbsolutePath().substring(l), classNameCondition);
}
}
if (!file.isFile()) continue;
try {
ZipFile zip = new ZipFile(file);
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()) {
String entry = ((Object)entries.nextElement()).toString();
if (!entry.endsWith(".class")) continue;
tryAddClass(classes, entry, classNameCondition);
}
zip.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return classes;
}

private static void tryAddClass(List<Class<?>> classes, String fileName, Condition<String> classNameCondition) {
String className = fileName.substring(0, fileName.length() - 6);
className = className.replace('\\', '.');
className = className.replace('/', '.');
if (classNameCondition == null || classNameCondition.isTrue(className)) {
Class<?> clazz = null;
try {
clazz = Knot.getClass(className);
} catch (Throwable e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
}
if (clazz != null) {
classes.add(clazz);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.minecraft.core.net.command.ClientPlayerCommandSender;
import net.minecraft.core.net.command.CommandHandler;
import net.minecraft.core.net.command.CommandSender;
import net.minecraft.core.util.helper.MathHelper;
import net.minecraft.core.util.phys.Vec3d;
import net.minecraft.core.world.Dimension;
import net.minecraft.core.world.World;
Expand Down Expand Up @@ -70,7 +71,7 @@ public boolean hasAdmin() {
return Vec3d.createVector(this.mc.objectMouseOver.x, this.mc.objectMouseOver.y, this.mc.objectMouseOver.z);
}
Vec3d playerCoordinates = this.getCoordinates(true);
return Vec3d.createVector(playerCoordinates.xCoord, playerCoordinates.yCoord, playerCoordinates.zCoord);
return Vec3d.createVector(MathHelper.floor_double(playerCoordinates.xCoord), MathHelper.floor_double(playerCoordinates.yCoord), MathHelper.floor_double(playerCoordinates.zCoord));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class CommanderCommandManager {
GameModeCommand.register(DISPATCHER);
WeatherCommand.register(DISPATCHER);
SpawnCommand.register(DISPATCHER);
PlaceCommand.register(DISPATCHER);
// GiveCommand.register(DISPATCHER);
// HelpCommand.register(DISPATCHER);
// GenerateCommand.register(DISPATCHER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import net.minecraft.core.net.command.ServerPlayerCommandSender;
import net.minecraft.core.net.packet.Packet3Chat;
import net.minecraft.core.util.helper.AES;
import net.minecraft.core.util.helper.MathHelper;
import net.minecraft.core.util.phys.Vec3d;
import net.minecraft.core.world.World;
import net.minecraft.server.MinecraftServer;
Expand Down Expand Up @@ -65,7 +66,8 @@ public boolean hasAdmin() {

@Override
public @NotNull Vec3d getBlockCoordinates() {
return this.getCoordinates(true);
Vec3d coordinates = this.getCoordinates(true);
return Vec3d.createVector(MathHelper.floor_double(coordinates.xCoord), MathHelper.floor_double(coordinates.yCoord), MathHelper.floor_double(coordinates.zCoord));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public Achievement parse(StringReader reader) throws CommandSyntaxException {
final String string = reader.readString();

for (Achievement achievement : AchievementList.achievementList) {
if (((StatNameAccessor)achievement).statName().equals(string) || (((StatNameAccessor)achievement).statName().startsWith("achievement.") && ((StatNameAccessor)achievement).statName().substring("achievement.".length()).equals(string))) {
if (CommanderHelper.matchesKeyString(((StatNameAccessor)achievement).statName(), string)) {
return achievement;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import net.minecraft.core.entity.EntityDispatcher;
import net.minecraft.core.lang.I18n;
import net.minecraft.core.util.collection.Pair;
import net.pedroricardo.commander.CommanderHelper;

import java.util.Arrays;
import java.util.Collection;
Expand All @@ -31,7 +32,7 @@ public Pair<Block, Integer> parse(StringReader reader) throws CommandSyntaxExcep
Block block = null;
for (Block blockInList : Block.blocksList) {
if (blockInList == null) continue;
if (blockInList.getKey().equals(string) || (blockInList.getKey().startsWith("tile.") && blockInList.getKey().substring("tile.".length()).equals(string))) {
if (CommanderHelper.matchesKeyString(blockInList.getKey(), string)) {
block = blockInList;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package net.pedroricardo.commander.content.arguments;

import com.b100.utils.Utils;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import net.fabricmc.loader.impl.lib.sat4j.specs.Constr;
import net.minecraft.core.achievement.Achievement;
import net.minecraft.core.achievement.AchievementList;
import net.minecraft.core.block.Block;
import net.minecraft.core.lang.I18n;
import net.minecraft.core.net.command.commands.GenerateCommand;
import net.minecraft.core.util.collection.Pair;
import net.minecraft.core.util.helper.ReflectionHelper;
import net.minecraft.core.world.generate.feature.WorldFeature;
import net.pedroricardo.commander.Commander;
import net.pedroricardo.commander.CommanderHelper;
import net.pedroricardo.commander.mixin.StatNameAccessor;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.concurrent.CompletableFuture;

public class WorldFeatureArgumentType implements ArgumentType<WorldFeature> {
private static final Collection<String> EXAMPLES = Arrays.asList("achievement.acquireIron", "acquireIron");

public static ArgumentType<WorldFeature> worldFeature() {
return new WorldFeatureArgumentType();
}

@Override
public WorldFeature parse(StringReader reader) throws CommandSyntaxException {
final String string = reader.readString();
Class<? extends WorldFeature> worldFeatureClass = null;

for (Map.Entry<String, Class<? extends WorldFeature>> entry : CommanderHelper.WORLD_FEATURES.entrySet()) {
if (CommanderHelper.matchesKeyString(entry.getKey(), string)) {
worldFeatureClass = entry.getValue();
}
}

if (worldFeatureClass == null) throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(reader);

boolean hasParameters = false;
Constructor<?> constructor = null;

for (Constructor<?> c : worldFeatureClass.getConstructors()) {
constructor = c;
if (c.getParameters().length != 0) hasParameters = true;
}

if (!hasParameters && constructor != null) {
try {
return (WorldFeature) constructor.newInstance();
} catch (Exception e) {
throw new CommandSyntaxException(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument(), () -> I18n.getInstance().translateKey("argument_types.commander.world_feature.invalid_world_feature"));
}
}

if (reader.canRead() && reader.peek() == '[') {
List<Object> parameters = new ArrayList<>();
constructor = null;

int cursor = reader.getCursor();

for (Constructor<?> c : worldFeatureClass.getConstructors()) {
reader.setCursor(cursor);
for (Parameter parameter : c.getParameters()) {
reader.skip();
reader.skipWhitespace();
int cursor2 = reader.getCursor();
if (parameter.getType() == Integer.TYPE) {
parameters.add(reader.readInt());
} else if (parameter.getType() == Block.class) {
parameters.add(parseBlock(reader));
} else if (parameter.getType() == String.class) {
parameters.add(reader.readString());
} else {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(reader);
}
reader.skipWhitespace();
if (!reader.canRead() || (reader.peek() != ',' && reader.peek() != ']')) {
reader.setCursor(cursor2);
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(reader);
}
}
constructor = c;
}
if (constructor != null && reader.canRead() && reader.peek() == ']') {
reader.skip();
try {
return (WorldFeature) constructor.newInstance(Utils.toArray(Object.class, parameters));
} catch (Exception e) {
Commander.LOGGER.info(e.toString());
throw new CommandSyntaxException(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument(), () -> I18n.getInstance().translateKey("argument_types.commander.world_feature.invalid_world_feature"));
}
}
}
throw new CommandSyntaxException(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument(), () -> I18n.getInstance().translateKey("argument_types.commander.world_feature.invalid_world_feature"));
}

private static Block parseBlock(StringReader reader) throws CommandSyntaxException {
final String string = reader.readString();

for (Block blockInList : Block.blocksList) {
if (blockInList == null) continue;
if (CommanderHelper.matchesKeyString(blockInList.getKey(), string)) {
return blockInList;
}
}
throw new CommandSyntaxException(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument(), () -> I18n.getInstance().translateKey("argument_types.commander.block.invalid_block"));
}

@Override
public <S> CompletableFuture<Suggestions> listSuggestions(final CommandContext<S> context, final SuggestionsBuilder builder) {
String remaining = builder.getRemainingLowerCase();
for (Map.Entry<String, Class<? extends WorldFeature>> entry : CommanderHelper.WORLD_FEATURES.entrySet()) {
Optional<String> optional = CommanderHelper.getStringToSuggest(entry.getKey(), remaining);
optional.ifPresent(builder::suggest);
}
return builder.buildFuture();
}

@Override
public Collection<String> getExamples() {
return EXAMPLES;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package net.pedroricardo.commander.content.commands;

import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.tree.CommandNode;
import net.minecraft.core.util.phys.Vec3d;
import net.minecraft.core.world.generate.feature.WorldFeature;
import net.pedroricardo.commander.content.CommanderCommandSource;
import net.pedroricardo.commander.content.arguments.IntegerCoordinatesArgumentType;
import net.pedroricardo.commander.content.arguments.WorldFeatureArgumentType;
import net.pedroricardo.commander.content.exceptions.CommanderExceptions;
import net.pedroricardo.commander.content.helpers.IntegerCoordinates;

import java.util.Collections;

@SuppressWarnings("unchecked")
public class PlaceCommand {
public static void register(CommandDispatcher<CommanderCommandSource> dispatcher) {
CommandNode<Object> command = dispatcher.register((LiteralArgumentBuilder) LiteralArgumentBuilder.literal("place")
.then((RequiredArgumentBuilder) RequiredArgumentBuilder.argument("feature", WorldFeatureArgumentType.worldFeature())
.executes(c -> {
CommanderCommandSource source = (CommanderCommandSource) c.getSource();
WorldFeature feature = c.getArgument("feature", WorldFeature.class);
Vec3d coordinates = ((CommanderCommandSource) c.getSource()).getBlockCoordinates();

if (coordinates == null) throw CommanderExceptions.notInWorld().create();

feature.generate(source.getWorld(), source.getWorld().rand, (int)coordinates.xCoord, (int)coordinates.yCoord, (int)coordinates.zCoord);
return Command.SINGLE_SUCCESS;
})));
dispatcher.register((LiteralArgumentBuilder) LiteralArgumentBuilder.literal("generate")
.redirect(command));
dispatcher.register((LiteralArgumentBuilder) LiteralArgumentBuilder.literal("gen")
.redirect(command));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ private void renderSingleSuggestionLine(FontRenderer fontRenderer, String text,

private List<String> getCommandUsage(int cursor) {
List<String> commandUsage = new ArrayList<>();
if (this.parseResults == null) return commandUsage;
if (this.parseResults == null || this.parseResults.getContext().getNodes().isEmpty()) return commandUsage;
for (Map.Entry<CommandNode<CommanderCommandSource>, String> entry : CommanderCommandManager.getDispatcher().getSmartUsage(this.parseResults.getContext().findSuggestionContext(cursor).parent, this.commandSource).entrySet()) {
if (entry.getKey() instanceof LiteralCommandNode) continue;
commandUsage.add(entry.getValue());
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/lang/commander/en_US.lang
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ argument_types.commander.time.invalid_unit=Invalid unit
argument_types.commander.time.tick_count_too_low=Tick count must not be less than %s, found %s
argument_types.commander.game_mode.invalid_game_mode=Invalid game mode
argument_types.commander.weather.invalid_weather=Invalid weather
argument_types.commander.world_feature.invalid_world_feature=Invalid world feature
commands.commander.time.query=The time is %s
commands.commander.time.set=Set the time to %s
commands.commander.achievement.grant.exception_already_has_achievement=Player already has achievement
Expand Down

0 comments on commit 58b9e4e

Please sign in to comment.