Skip to content

Commit 66e6772

Browse files
edewitvorburger
andauthored
made whenInside locations work (#426)
Co-authored-by: Michael Vorburger ⛑️ <[email protected]>
1 parent 30b8749 commit 66e6772

File tree

10 files changed

+138
-12
lines changed

10 files changed

+138
-12
lines changed

api-jvm-impl/src/main/java/ch/vorburger/minecraft/storeys/japi/impl/EventsImpl.java

+10
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,16 @@ class EventsImpl implements Events, Unregisterable {
8686
}));
8787
}
8888

89+
@Override public void whenInside(String locationName, Callback callback) {
90+
unregistrables.add(eventService.registerInsideLocation(locationName, player -> {
91+
try {
92+
invokeCallback(player, callback);
93+
} catch (Exception e) {
94+
LOG.error("whenInside() callback failure", e);
95+
}
96+
}));
97+
}
98+
8999
@Override public void whenEntityRightClicked(String entityName, Callback callback) {
90100
ch.vorburger.minecraft.storeys.japi.impl.events.Callback otherCallback = invoker -> {
91101
invokeCallback(invoker, callback);

api-jvm-impl/src/main/java/ch/vorburger/minecraft/storeys/japi/impl/events/EventService.java

+22-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package ch.vorburger.minecraft.storeys.japi.impl.events;
2020

2121
import ch.vorburger.minecraft.osgi.api.PluginInstance;
22+
import ch.vorburger.minecraft.storeys.japi.PlayerInsideEvent;
2223
import ch.vorburger.minecraft.storeys.japi.impl.Unregisterable;
2324
import java.util.Collection;
2425
import java.util.Collections;
@@ -39,12 +40,13 @@
3940
import org.spongepowered.api.event.network.ClientConnectionEvent.Join;
4041
import org.spongepowered.api.text.Text;
4142

42-
@Singleton
43-
public class EventService implements AutoCloseable {
43+
@Singleton public class EventService implements AutoCloseable {
4444

4545
private static final Logger LOG = LoggerFactory.getLogger(EventService.class);
4646

4747
private final Collection<Callback> onPlayerJoinCallbacks = new ConcurrentLinkedQueue<>();
48+
49+
private final Map<String, Collection<Callback>> onPlayerInsideCallbacks = new ConcurrentHashMap<>();
4850
private final Map<String, Collection<Callback>> onInteractEntityEventCallbacks = new ConcurrentHashMap<>();
4951

5052
private final EventManager eventManager;
@@ -68,10 +70,28 @@ public void setPluginInstance(PluginInstance plugin) {
6870
}
6971
}
7072

73+
@Listener public void onInsideLocation(PlayerInsideEvent event) throws Exception {
74+
final String locationName = event.getLocationName();
75+
Collection<Callback> callbacks = onPlayerInsideCallbacks.get(locationName);
76+
if (callbacks != null) {
77+
for (Callback callback : callbacks) {
78+
callback.call(event.getEffectedPlayer());
79+
}
80+
} else {
81+
LOG.warn("Unknown Location: {}", locationName);
82+
}
83+
}
84+
7185
public Unregisterable registerPlayerJoin(Callback callback) {
7286
return add(onPlayerJoinCallbacks, callback);
7387
}
7488

89+
public Unregisterable registerInsideLocation(String locationName, Callback callback) {
90+
Collection<Callback> callbacks = onPlayerInsideCallbacks.computeIfAbsent(locationName,
91+
name -> new ConcurrentLinkedQueue<>());
92+
return add(callbacks, callback);
93+
}
94+
7595
public Unregisterable registerInteractEntity(String entityName, Callback callback) {
7696
Collection<Callback> callbacks = onInteractEntityEventCallbacks.computeIfAbsent(entityName, name -> new ConcurrentLinkedQueue<>());
7797
return add(callbacks, callback);

api-jvm/src/main/java/ch/vorburger/minecraft/storeys/japi/Events.java

+1
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@ public interface Events {
2727

2828
void whenPlayerJoins(Callback callback);
2929

30+
void whenInside(String locationName, Callback callback);
3031
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* ch.vorburger.minecraft.storeys
3+
*
4+
* Copyright (C) 2016 - 2018 Michael Vorburger.ch <[email protected]>
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+
import org.spongepowered.api.entity.living.player.Player;
22+
import org.spongepowered.api.event.Cancellable;
23+
import org.spongepowered.api.event.cause.Cause;
24+
import org.spongepowered.api.event.impl.AbstractEvent;
25+
26+
public class PlayerInsideEvent extends AbstractEvent implements Cancellable {
27+
private final Player player;
28+
private final Cause cause;
29+
private final String locationName;
30+
private boolean cancelled = false;
31+
32+
public PlayerInsideEvent(Player player, String locationName, Cause cause) {
33+
this.player = player;
34+
this.locationName = locationName;
35+
this.cause = cause;
36+
}
37+
38+
@Override public Cause getCause() {
39+
return cause;
40+
}
41+
42+
@Override public boolean isCancelled() {
43+
return cancelled;
44+
}
45+
46+
@Override public void setCancelled(boolean cancel) {
47+
this.cancelled = cancel;
48+
}
49+
50+
public Player getEffectedPlayer() {
51+
return this.player;
52+
}
53+
54+
public String getLocationName() {
55+
return locationName;
56+
}
57+
58+
@Override public String toString() {
59+
return "PlayerInsideEvent{" + "player=" + player + ", locationName='" + locationName + '\'' + '}';
60+
}
61+
}

docs/testing.md

+7-2
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@ Now test that you can make a new project:
2222
1. Add
2323
* Events > When / `demo`
2424
* Actions > Title `Hello!`
25-
* Actions > `Piggy` speaks `Hello!`
26-
1. Click _upload code_ button _(TODO perhaps we could auto-save, later?)_
25+
* Actions > `Piggy` speaks `Hello!`
2726
1. `/demo` command in Minecraft should now make the entity _Piggy_ speak
27+
1. Drag a whenInside block and add a name of the region `trigger`
28+
* Your player will get a special axe to "draw" the region with
29+
* Use left mouse to set the first point of a box
30+
* Right mouse to set the second point of a box
31+
* Now any time a player enters the block beneath will be executed
2832

2933
_TODO Update the following, after Blockly will be made to reload previous projects?_
3034

@@ -43,6 +47,7 @@ _TODO Update the following, after Blockly will be made to reload previous projec
4347

4448
1. `/new`
4549
1. Verify [`test.js`](../minecraft-server-test-data/config/storeys-web/new-scripts/test.js) happened as expected
50+
1. _TODO Walk to the cacti and jump on top and make sure a "you jumped!" is shown as title
4651
1. Edit `test.js` to change `m.title("Hello");` to `m.title("hello, world");`
4752
1. `/new`
4853
1. Verify title shown changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
locations=[
2+
{
3+
hitbox {
4+
worldName=world
5+
x1=229
6+
x2=227
7+
y1=65
8+
y2=64
9+
z1=215
10+
z2=217
11+
}
12+
name=box
13+
player=fb79c1a9-72bd-34dc-9775-c2ac868d7ccf
14+
}
15+
]

minecraft-server-test-data/config/storeys-web/new-scripts/test.js

+5
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@ e.whenCommand("new", function callback(m) {
66
m.cmd("/say Go fishing with the rod in your inventory..");
77
}
88
});
9+
10+
// box is the location on top of the bushes
11+
e.whenInside("box", function(m) {
12+
m.title('you jumped!');
13+
});

test-mineflayer/storeys.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ describe("Storeys plugin test", () => {
2222
// then
2323
bot.on('messagestr', (msg, _, json) => {
2424
if (msg !== "Player joined the game") {
25-
expect(msg).to.equal("Click here to open Scratch and MAKE actions");
25+
expect(msg).to.equal("Click here to open a browser and start MAKE actions");
2626
done();
2727
}
2828
});

web/src/main/java/ch/vorburger/minecraft/storeys/web/LocationToolListener.java

+14-5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import ch.vorburger.minecraft.storeys.events.Condition;
2323
import ch.vorburger.minecraft.storeys.events.ConditionService;
2424
import ch.vorburger.minecraft.storeys.events.LocatableInBoxCondition;
25+
import ch.vorburger.minecraft.storeys.japi.PlayerInsideEvent;
2526
import ch.vorburger.minecraft.storeys.japi.impl.Unregisterable;
2627
import ch.vorburger.minecraft.storeys.model.LocationToolAction;
2728
import ch.vorburger.minecraft.storeys.web.location.LocationHitBox;
@@ -51,25 +52,33 @@
5152
import org.spongepowered.api.event.EventManager;
5253
import org.spongepowered.api.event.Listener;
5354
import org.spongepowered.api.event.block.InteractBlockEvent;
55+
import org.spongepowered.api.event.cause.Cause;
56+
import org.spongepowered.api.event.cause.EventContext;
5457
import org.spongepowered.api.event.cause.EventContextKeys;
5558
import org.spongepowered.api.event.game.state.GameStoppingServerEvent;
5659
import org.spongepowered.api.item.inventory.ItemStackSnapshot;
5760
import org.spongepowered.api.text.Text;
5861
import org.spongepowered.api.world.Location;
5962
import org.spongepowered.api.world.World;
6063

61-
@Singleton
62-
public class LocationToolListener {
64+
@Singleton public class LocationToolListener {
6365
private static final Logger LOG = LoggerFactory.getLogger(LocationToolListener.class);
6466
private final Map<String, Pair<Location<World>, Location<World>>> playerBoxLocations = new ConcurrentHashMap<>();
6567
private final Map<String, Unregisterable> conditionRegistrations = new ConcurrentHashMap<>();
6668
private final ConditionService conditionService;
6769
private final ConfigurationLoader<CommentedConfigurationNode> configurationLoader;
6870

71+
private final EventContext eventContext;
72+
private EventManager eventManager;
73+
private final PluginInstance plugin;
74+
6975
@Inject public LocationToolListener(PluginInstance plugin, EventManager eventManager, ConditionService conditionService,
7076
ConfigurationLoader<CommentedConfigurationNode> loader) {
7177
TypeSerializerCollection.defaults().register(LocationPairSerializer.TYPE, new LocationPairSerializer());
7278
eventManager.registerListeners(plugin, this);
79+
this.eventManager = eventManager;
80+
this.plugin = plugin;
81+
this.eventContext = EventContext.builder().add(EventContextKeys.PLUGIN, plugin.getPluginContainer()).build();
7382
this.conditionService = conditionService;
7483
configurationLoader = loader;
7584

@@ -131,9 +140,9 @@ private void registerCondition(UUID player, String locationName, Pair<Location<W
131140
if (unregisterable != null) {
132141
unregisterable.unregister();
133142
}
134-
ConditionService.ConditionServiceRegistration registration = conditionService.register(condition,
135-
// TODO properly implement full support for this old feature in the new api-jvm
136-
(Player p) -> LOG.warn("TODO inform the player that someone was inside the region {}", p));
143+
ConditionService.ConditionServiceRegistration registration = conditionService.register(condition, (p) -> {
144+
eventManager.post(new PlayerInsideEvent(p, locationName, Cause.of(eventContext, plugin)));
145+
});
137146
conditionRegistrations.put(name, registration);
138147
}
139148

web/src/main/java/ch/vorburger/minecraft/storeys/web/LoginCommand.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ private String getSystemPropertyEnvVarOrDefault(String propertyName, String defa
6363
}
6464

6565
@Override public CommandCallable callable() {
66-
return CommandSpec.builder().description(Text.of("Login into ScratchX web interface")) // .permission("storeys.command.make")
66+
return CommandSpec.builder().description(Text.of("Open the browser and start your story")) // .permission("storeys.command.make")
6767
.arguments(GenericArguments.flags().permissionFlag("storeys.command.make.beta", "b").buildWith(GenericArguments.none()))
6868
.executor(this).build();
6969
}
@@ -80,7 +80,7 @@ private String getSystemPropertyEnvVarOrDefault(String propertyName, String defa
8080
String code = tokenProvider.getCode(player);
8181
String url = String.format("%s?code=%s", scratchGui, code);
8282

83-
src.sendMessage(Text.builder("Click here to open Scratch and MAKE actions").onClick(TextActions.openUrl(new URL(url)))
83+
src.sendMessage(Text.builder("Click here to open a browser and start MAKE actions").onClick(TextActions.openUrl(new URL(url)))
8484
.color(TextColors.GOLD).build());
8585
});
8686
} else {

0 commit comments

Comments
 (0)