Skip to content

Commit dd87496

Browse files
committed
WIP of new JVM API (incl. Unregistrable Script)
1 parent 5a231a5 commit dd87496

File tree

36 files changed

+547
-40
lines changed

36 files changed

+547
-40
lines changed

api-jvm-impl/build.gradle

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
dependencies {
3+
api project(':api-jvm')
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* ch.vorburger.minecraft.storeys
3+
*
4+
* Copyright (C) 2016 - 2018 Michael Vorburger.ch <mike@vorburger.ch>
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published
8+
* by the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
package ch.vorburger.minecraft.storeys.japi.impl;
20+
21+
import ch.vorburger.minecraft.storeys.japi.Callback;
22+
import ch.vorburger.minecraft.storeys.japi.Events;
23+
import ch.vorburger.minecraft.storeys.japi.Script;
24+
import ch.vorburger.minecraft.storeys.japi.util.CommandExceptions;
25+
import ch.vorburger.minecraft.storeys.japi.util.Texts;
26+
import java.util.Collection;
27+
import java.util.Optional;
28+
import java.util.concurrent.ConcurrentLinkedQueue;
29+
import org.spongepowered.api.Sponge;
30+
import org.spongepowered.api.command.CommandMapping;
31+
import org.spongepowered.api.command.CommandResult;
32+
import org.spongepowered.api.command.CommandSource;
33+
import org.spongepowered.api.command.spec.CommandSpec;
34+
35+
/**
36+
* {@link Events} implementation.
37+
*
38+
* Created via {@link Scripts}.
39+
*
40+
* The "lifecycle" of this is NOT a Singleton,
41+
* but one for each new (possibly reloaded) {@link Script} instance.
42+
*/
43+
class EventsImpl implements Events, Unregisterable {
44+
45+
private final Object plugin;
46+
private final CommandSource source;
47+
private final Collection<Unregisterable> unregistrables = new ConcurrentLinkedQueue<>();
48+
49+
EventsImpl(Object plugin, CommandSource source) {
50+
this.plugin = plugin;
51+
this.source = source;
52+
}
53+
54+
@Override public void whenCommand(String name, Callback callback) {
55+
CommandSpec spec = CommandSpec.builder().executor((src, args) -> {
56+
CommandExceptions.doOrThrow("/" + name, () -> callback.invoke(new MinecraftJvmImpl(src)));
57+
return CommandResult.success();
58+
}).build();
59+
Optional<CommandMapping> opt = Sponge.getCommandManager().register(plugin, spec, name);
60+
if (!opt.isPresent()) {
61+
source.sendMessage(Texts.inRed("Could not register /" + name));
62+
return;
63+
}
64+
unregistrables.add(() -> Sponge.getCommandManager().removeMapping(opt.get()));
65+
}
66+
67+
@Override public void unregister() {
68+
for (Unregisterable unregisterable : unregistrables) {
69+
unregisterable.unregister();
70+
}
71+
}
72+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* ch.vorburger.minecraft.storeys
3+
*
4+
* Copyright (C) 2016 - 2018 Michael Vorburger.ch <mike@vorburger.ch>
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published
8+
* by the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
package ch.vorburger.minecraft.storeys.japi.impl;
20+
21+
import static java.util.Objects.requireNonNull;
22+
23+
import ch.vorburger.minecraft.storeys.japi.Events;
24+
import ch.vorburger.minecraft.storeys.japi.Minecraft;
25+
import org.spongepowered.api.Sponge;
26+
import org.spongepowered.api.command.CommandSource;
27+
import org.spongepowered.api.entity.living.player.Player;
28+
29+
/**
30+
* {@link Minecraft} implementation.
31+
*
32+
* Created indirectly (by EventsImpl) via {@link Scripts}.
33+
*
34+
* The "lifecycle" of this is NOT a Singleton,
35+
* but one for each instance (not just kind of) of an event registered on {@link Events},
36+
* such as custom command, when right clicked, when player joined, when inside, etc.
37+
*/
38+
class MinecraftJvmImpl implements Minecraft {
39+
40+
private final CommandSource source;
41+
42+
MinecraftJvmImpl(CommandSource source) {
43+
this.source = source;
44+
}
45+
46+
@Override public void cmd(String command) {
47+
String commandWithoutSlash = requireNonNull(command, "command").trim();
48+
if (commandWithoutSlash.startsWith("/")) {
49+
commandWithoutSlash = commandWithoutSlash.substring(1);
50+
}
51+
Sponge.getCommandManager().process(source, requireNonNull(commandWithoutSlash, "commandWithoutSlash"));
52+
}
53+
54+
@Override public Player player() {
55+
// TODO if (source instanceof Player), else... error handling TBD (not just log, but explain it to source)
56+
return (Player) source;
57+
}
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* ch.vorburger.minecraft.storeys
3+
*
4+
* Copyright (C) 2016 - 2018 Michael Vorburger.ch <mike@vorburger.ch>
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published
8+
* by the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
package ch.vorburger.minecraft.storeys.japi.impl;
20+
21+
import ch.vorburger.minecraft.storeys.japi.Script;
22+
import com.google.errorprone.annotations.CheckReturnValue;
23+
import org.spongepowered.api.command.CommandSource;
24+
25+
public final class Scripts {
26+
27+
// TODO Make Scripts @Inject-able...
28+
29+
// TODO CommandSource argument here still smells wrong (it should be "later")
30+
31+
@CheckReturnValue public static Unregisterable init(Object plugin, CommandSource source, Script script) {
32+
EventsImpl e = new EventsImpl(plugin, source);
33+
script.init(e);
34+
return e;
35+
}
36+
37+
private Scripts() {
38+
}
39+
}

storeys/src/main/java/ch/vorburger/minecraft/storeys/events/Unregisterable.java renamed to api-jvm-impl/src/main/java/ch/vorburger/minecraft/storeys/japi/impl/Unregisterable.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* You should have received a copy of the GNU Affero General Public License
1717
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1818
*/
19-
package ch.vorburger.minecraft.storeys.events;
19+
package ch.vorburger.minecraft.storeys.japi.impl;
2020

2121
public interface Unregisterable {
2222

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* ch.vorburger.minecraft.storeys
3+
*
4+
* Copyright (C) 2016 - 2018 Michael Vorburger.ch <mike@vorburger.ch>
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published
8+
* by the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
package ch.vorburger.minecraft.storeys.japi.util;
20+
21+
import java.util.concurrent.Callable;
22+
import org.slf4j.Logger;
23+
import org.slf4j.LoggerFactory;
24+
import org.spongepowered.api.command.CommandException;
25+
26+
/**
27+
* Utilities for {@link CommandException}.
28+
*
29+
* @author Michael Vorburger.ch
30+
*/
31+
public final class CommandExceptions {
32+
33+
// Copy/pasted from https://github.com/vorburger/ch.vorburger.minecraft.osgi/blob/master/ch.vorburger.minecraft.osgi.api/src/main/java/ch/vorburger/minecraft/utils/CommandExceptions.java
34+
35+
private static final Logger LOG = LoggerFactory.getLogger(CommandExceptions.class);
36+
37+
private CommandExceptions() {
38+
}
39+
40+
/**
41+
* Invoke 'callable' and return its value,
42+
* or rethrow any Exception from it wrapped in a CommandException,
43+
* with description.
44+
*
45+
* @param description a humand-readable description of the Callable (used in the CommandException)
46+
* @param callable the code to invoke
47+
* @return the value returned by the callable
48+
* @throws CommandException in case the callable failed with an Exception
49+
*/
50+
public static <T> T getOrThrow(String description, Callable<T> callable) throws CommandException {
51+
try {
52+
return callable.call();
53+
} catch (Exception cause) {
54+
// TODO see isDeveloper() idea in Texts.fromThrowable
55+
throw new CommandException(Texts.fromThrowable(description, cause), cause, true);
56+
}
57+
}
58+
59+
public static void doOrThrow(String description, RunnableWithException runnable) throws CommandException {
60+
try {
61+
runnable.run();
62+
} catch (Exception cause) {
63+
// TODO once the cause is properly throw to the user incl. stack trace, this log is probably redundant; then remove?
64+
LOG.error("doOrThrow()", cause);
65+
// TODO see isDeveloper() idea in Texts.fromThrowable
66+
throw new CommandException(Texts.fromThrowable(description, cause), cause, true);
67+
}
68+
}
69+
70+
public static CommandException create(String message) {
71+
return new CommandException(Texts.inRed(message));
72+
}
73+
74+
@FunctionalInterface
75+
public interface RunnableWithException {
76+
void run() throws Exception;
77+
}
78+
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* ch.vorburger.minecraft.storeys
3+
*
4+
* Copyright (C) 2016 - 2018 Michael Vorburger.ch <mike@vorburger.ch>
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published
8+
* by the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
package ch.vorburger.minecraft.storeys.japi.util;
20+
21+
import org.spongepowered.api.text.Text;
22+
import org.spongepowered.api.text.format.TextColors;
23+
24+
/**
25+
* Utilities for {@link Text}.
26+
*
27+
* @author Michael Vorburger.ch
28+
*/
29+
public final class Texts {
30+
31+
// Copy/pasted from https://github.com/vorburger/ch.vorburger.minecraft.osgi/blob/master/ch.vorburger.minecraft.osgi.api/src/main/java/ch/vorburger/minecraft/utils/Texts.java
32+
33+
private Texts() {
34+
}
35+
36+
public static Text fromThrowable(String prefix, Throwable throwable) {
37+
// TODO have a Player isDeveloper flag (or Permission, probably..)
38+
// developers get to see the cause stack trace? ;) Noob do not.
39+
return Text.builder().color(TextColors.RED).append(Text.of(prefix + throwable.getMessage())).build();
40+
// TODO add StackTrace here - with links being able to click on to jump into sources!!!
41+
}
42+
43+
public static Text inRed(String content) {
44+
return Text.builder().color(TextColors.RED).append(Text.of(content)).build();
45+
}
46+
}

api-jvm/build.gradle

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
// TODO Build refactoring so that this module inherits only spongeapi WITHOUT everything else from the subprojects {} in ../build.gradle
3+
4+
dependencies {
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* ch.vorburger.minecraft.storeys
3+
*
4+
* Copyright (C) 2016 - 2018 Michael Vorburger.ch <mike@vorburger.ch>
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published
8+
* by the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
package ch.vorburger.minecraft.storeys.japi;
20+
21+
@FunctionalInterface
22+
public interface Callback {
23+
24+
void invoke(Minecraft m) throws Exception;
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* ch.vorburger.minecraft.storeys
3+
*
4+
* Copyright (C) 2016 - 2018 Michael Vorburger.ch <mike@vorburger.ch>
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published
8+
* by the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
package ch.vorburger.minecraft.storeys.japi;
20+
21+
public interface Events {
22+
23+
// This is intentionally NOT returning CommandResult, to keep it simple, for scripting.
24+
void whenCommand(String name, Callback callback);
25+
26+
// TODO add more "event handlers" here; see
27+
// https://github.com/OASIS-learn-study/minecraft-storeys-maker/blob/develop/api/src/main/typescript/observable-wrapper.ts
28+
}

0 commit comments

Comments
 (0)