Skip to content

Commit fdedd70

Browse files
committed
Add virtual spaker API
1 parent f81baea commit fdedd70

File tree

8 files changed

+163
-11
lines changed

8 files changed

+163
-11
lines changed

api/src/main/java/com/craftmend/openaudiomc/api/WorldApi.java

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package com.craftmend.openaudiomc.api;
22

3-
import com.craftmend.openaudiomc.api.exceptions.InvalidRegionException;
4-
import com.craftmend.openaudiomc.api.exceptions.InvalidThreadException;
5-
import com.craftmend.openaudiomc.api.exceptions.UnknownWorldException;
3+
import com.craftmend.openaudiomc.api.exceptions.*;
4+
import com.craftmend.openaudiomc.api.media.Media;
65
import com.craftmend.openaudiomc.api.regions.AudioRegion;
76
import com.craftmend.openaudiomc.api.regions.RegionMediaOptions;
87
import com.craftmend.openaudiomc.api.speakers.BasicSpeaker;
8+
import com.craftmend.openaudiomc.api.speakers.ExtraSpeakerOptions;
9+
import com.craftmend.openaudiomc.api.speakers.SpeakerType;
910
import org.jetbrains.annotations.NotNull;
1011
import org.jetbrains.annotations.Nullable;
1112

@@ -54,6 +55,43 @@ static WorldApi getInstance() {
5455
@Nullable
5556
BasicSpeaker getSpeakerAt(int x, int y, int z, @NotNull String world);
5657

58+
/**
59+
* Register a virtual speaker at a location.
60+
* This is a location that will play sound as if there's a speaker there, but there isn't.
61+
*
62+
* @param x x
63+
* @param y y
64+
* @param z z
65+
* @param world world
66+
* @param String media source
67+
* @param speakerType speaker type
68+
* @param radius radius
69+
* @param extraOptions extra options (redstone requirement, loop, etc)
70+
*
71+
* @throws InvalidThreadException if called from the main thread.
72+
* This is to prevent blocking the main thread with the underlying Sqlite database
73+
* @throws InvalidLocationException if the location is not valid (this location is already occupied by a real or virtual speaker)
74+
*/
75+
void registerVirtualSpeaker(
76+
int x,
77+
int y,
78+
int z,
79+
@NotNull String world,
80+
@NotNull String media,
81+
SpeakerType speakerType,
82+
int radius,
83+
ExtraSpeakerOptions... extraOptions
84+
) throws InvalidThreadException, InvalidLocationException;
85+
86+
/**
87+
* Unregister a virtual speaker (which has been registered by the api)
88+
*
89+
* @param speaker speaker
90+
* @throws InvalidSpeakerException if the speaker is not valid (already unregistered, or not registered by the api)
91+
* @throws InvalidThreadException if called from the main thread.
92+
*/
93+
void unregisterVirtualSpeaker(@NotNull BasicSpeaker speaker) throws InvalidSpeakerException, InvalidThreadException;
94+
5795
/**
5896
* Register a region in a world.
5997
* Important:
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.craftmend.openaudiomc.api.exceptions;
2+
3+
/**
4+
* Thrown when a given location is not valid for a certain operation
5+
* (something is already there, or the location is not valid)
6+
*/
7+
public class InvalidLocationException extends RuntimeException {
8+
public InvalidLocationException(String message) {
9+
super(message);
10+
}
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.craftmend.openaudiomc.api.exceptions;
2+
3+
/**
4+
* Thrown when a given speaker is not valid for a certain operation
5+
* (when its null, or not placed/managed by the API initially)
6+
*/
7+
public class InvalidSpeakerException extends RuntimeException {
8+
public InvalidSpeakerException(String message) {
9+
super(message);
10+
}
11+
}

api/src/main/java/com/craftmend/openaudiomc/api/exceptions/InvalidThreadException.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@ public InvalidThreadException() {
99
super("This method can only be called from the main thread");
1010
}
1111

12+
public InvalidThreadException(String message) {
13+
super(message);
14+
}
15+
1216
}

api/src/main/java/com/craftmend/openaudiomc/api/speakers/BasicSpeaker.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,9 @@ public interface BasicSpeaker {
5959
*/
6060
boolean isRedstonePowered();
6161

62+
/**
63+
* If this speaker is a virtual speaker (managed by the API)
64+
* @return is virtual
65+
*/
66+
boolean isVirtual();
6267
}

plugin/src/main/java/com/craftmend/openaudiomc/generic/api/implementaions/WorldApiImpl.java

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
import com.craftmend.openaudiomc.OpenAudioMc;
44
import com.craftmend.openaudiomc.api.WorldApi;
5-
import com.craftmend.openaudiomc.api.exceptions.InvalidRegionException;
6-
import com.craftmend.openaudiomc.api.exceptions.InvalidThreadException;
7-
import com.craftmend.openaudiomc.api.exceptions.UnknownWorldException;
5+
import com.craftmend.openaudiomc.api.exceptions.*;
86
import com.craftmend.openaudiomc.api.media.Media;
97
import com.craftmend.openaudiomc.api.regions.AudioRegion;
108
import com.craftmend.openaudiomc.api.regions.RegionMediaOptions;
119
import com.craftmend.openaudiomc.api.speakers.BasicSpeaker;
10+
import com.craftmend.openaudiomc.api.speakers.ExtraSpeakerOptions;
11+
import com.craftmend.openaudiomc.api.speakers.SpeakerType;
1212
import com.craftmend.openaudiomc.generic.database.DatabaseService;
1313
import com.craftmend.openaudiomc.generic.platform.Platform;
1414
import com.craftmend.openaudiomc.spigot.OpenAudioMcSpigot;
@@ -19,17 +19,15 @@
1919
import com.craftmend.openaudiomc.spigot.modules.regions.registry.WorldRegionManager;
2020
import com.craftmend.openaudiomc.spigot.modules.speakers.SpeakerService;
2121
import com.craftmend.openaudiomc.spigot.modules.speakers.objects.MappedLocation;
22+
import com.craftmend.openaudiomc.spigot.modules.speakers.objects.Speaker;
2223
import lombok.AllArgsConstructor;
2324
import org.bukkit.Bukkit;
2425
import org.bukkit.ChatColor;
2526
import org.bukkit.Location;
2627
import org.jetbrains.annotations.NotNull;
2728
import org.jetbrains.annotations.Nullable;
2829

29-
import java.util.ArrayList;
30-
import java.util.Collection;
31-
import java.util.List;
32-
import java.util.Objects;
30+
import java.util.*;
3331

3432
public class WorldApiImpl implements WorldApi {
3533

@@ -64,6 +62,74 @@ public BasicSpeaker getSpeakerAt(int x, int y, int z, @NotNull String world) {
6462
return OpenAudioMc.getService(SpeakerService.class).getSpeaker(new MappedLocation(x, y, z, world));
6563
}
6664

65+
@Override
66+
public void registerVirtualSpeaker(int x, int y, int z, @NotNull String world, @NotNull String mediaSource, SpeakerType type, int radius, ExtraSpeakerOptions... options) throws InvalidThreadException, InvalidLocationException {
67+
Objects.requireNonNull(world, "World cannot be null");
68+
Objects.requireNonNull(mediaSource, "Media source cannot be null");
69+
70+
if (!Bukkit.isPrimaryThread()) {
71+
throw new InvalidThreadException();
72+
}
73+
74+
if (Bukkit.getWorld(world) == null) {
75+
throw new InvalidLocationException("World " + world + " does not exist");
76+
}
77+
78+
UUID id = UUID.randomUUID();
79+
MappedLocation location = new MappedLocation(
80+
x, y, z, world
81+
);
82+
83+
// check if there is already a speaker at this location
84+
if (getSpeakerAt(x, y, z, world) != null) {
85+
throw new InvalidLocationException("There is already a speaker at this location");
86+
}
87+
88+
// make the options a set
89+
EnumSet<ExtraSpeakerOptions> optionSet = EnumSet.noneOf(ExtraSpeakerOptions.class);
90+
Collections.addAll(optionSet, options);
91+
92+
// init speaker
93+
Speaker speaker = new Speaker(
94+
mediaSource,
95+
id,
96+
radius,
97+
location,
98+
type,
99+
optionSet
100+
);
101+
102+
OpenAudioMc.getService(SpeakerService.class).registerSpeaker(speaker);
103+
104+
// save to the database
105+
OpenAudioMc.getService(DatabaseService.class)
106+
.getRepository(Speaker.class)
107+
.save(speaker);
108+
}
109+
110+
@Override
111+
public void unregisterVirtualSpeaker(@NotNull BasicSpeaker speaker) throws InvalidSpeakerException, InvalidThreadException {
112+
Objects.requireNonNull(speaker, "Speaker cannot be null");
113+
114+
if (!speaker.isVirtual()) {
115+
throw new InvalidSpeakerException("Speaker is not virtual, only speakers managed by the API can be unregistered");
116+
}
117+
118+
if (Bukkit.isPrimaryThread()) {
119+
throw new InvalidThreadException("The unregister method should not be called from the main thread");
120+
}
121+
122+
// is this speaker actually here?
123+
if (getSpeakerAt(speaker.getLocation().getX(), speaker.getLocation().getY(), speaker.getLocation().getZ(), speaker.getLocation().getWorld()) == null) {
124+
throw new InvalidSpeakerException("Speaker is not registered");
125+
}
126+
127+
// unlist from service
128+
OpenAudioMc.getService(SpeakerService.class).unlistSpeaker(speaker.getLocation());
129+
// delete from database
130+
OpenAudioMc.getService(DatabaseService.class).getRepository(Speaker.class).delete((Speaker) speaker);
131+
}
132+
67133
@Override
68134
public void registerRegion(String worldName, String regionId, RegionMediaOptions regionMedia) throws InvalidRegionException, InvalidThreadException {
69135
Objects.requireNonNull(worldName, "World name cannot be null");

plugin/src/main/java/com/craftmend/openaudiomc/spigot/modules/speakers/SpeakerService.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.craftmend.openaudiomc.spigot.modules.speakers;
22

33
import com.craftmend.openaudiomc.OpenAudioMc;
4+
import com.craftmend.openaudiomc.api.speakers.Loc;
45
import com.craftmend.openaudiomc.generic.database.DatabaseService;
56
import com.craftmend.openaudiomc.generic.logging.OpenAudioLogger;
67
import com.craftmend.openaudiomc.generic.media.MediaService;
@@ -169,7 +170,10 @@ public SpeakerMedia getMedia(String source) {
169170
return speakerMedia;
170171
}
171172

172-
public void unlistSpeaker(MappedLocation location) {
173+
public void unlistSpeaker(Loc location) {
174+
if (!(location instanceof MappedLocation)) {
175+
throw new IllegalArgumentException("Location is not a MappedLocation");
176+
}
173177
speakerMap.remove(location);
174178
}
175179
}

plugin/src/main/java/com/craftmend/openaudiomc/spigot/modules/speakers/objects/MappedLocation.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,17 @@ public static MappedLocation fromBukkit(Location location) {
3939
return new MappedLocation(location.getBlockX(), location.getBlockY(), location.getBlockZ(), location.getWorld().getName());
4040
}
4141

42+
@Override
43+
public boolean equals(Object obj) {
44+
if (obj instanceof MappedLocation) {
45+
MappedLocation other = (MappedLocation) obj;
46+
return other.x == x && other.y == y && other.z == z && other.world.equals(world);
47+
}
48+
return false;
49+
}
50+
51+
public Loc toApiLoc() {
52+
return this;
53+
}
54+
4255
}

0 commit comments

Comments
 (0)