parent
621c006590
commit
961e4bc375
8 changed files with 290 additions and 39 deletions
7
DEVELOPMENT.md
Normal file
7
DEVELOPMENT.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
To see Minecraft source code: https://git.m724.eu/Minecon724/fabric-template-minimal-source
|
||||
|
||||
To setup NMS:
|
||||
1. Download BuildTools, move it into an empty directory and open terminal
|
||||
2. ```
|
||||
java -jar BuildTools.jar --rev 1.21.1 --remapped
|
||||
```
|
66
pom.xml
66
pom.xml
|
@ -12,6 +12,7 @@
|
|||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.spigot.version>1.21.1-R0.1-SNAPSHOT</project.spigot.version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
|
@ -54,6 +55,39 @@
|
|||
</executions>
|
||||
</plugin>
|
||||
<!-- end of this -->
|
||||
<plugin>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>specialsource-maven-plugin</artifactId>
|
||||
<version>2.0.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>remap</goal>
|
||||
</goals>
|
||||
<id>remap-obf</id>
|
||||
<configuration>
|
||||
<srgIn>org.spigotmc:minecraft-server:${project.spigot.version}:txt:maps-mojang</srgIn>
|
||||
<reverse>true</reverse>
|
||||
<remappedDependencies>org.spigotmc:spigot:${project.spigot.version}:jar:remapped-mojang</remappedDependencies>
|
||||
<remappedArtifactAttached>true</remappedArtifactAttached>
|
||||
<remappedClassifierName>remapped-obf-temp-dont-use</remappedClassifierName>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>remap</goal>
|
||||
</goals>
|
||||
<id>remap-spigot</id>
|
||||
<configuration>
|
||||
<inputFile>${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf-temp-dont-use.jar</inputFile>
|
||||
<srgIn>org.spigotmc:minecraft-server:${project.spigot.version}:csrg:maps-spigot</srgIn>
|
||||
<remappedDependencies>org.spigotmc:spigot:${project.spigot.version}:jar:remapped-obf</remappedDependencies>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
@ -66,13 +100,37 @@
|
|||
<id>dmulloy2-repo</id>
|
||||
<url>https://repo.dmulloy2.net/repository/public/</url>
|
||||
</repository>
|
||||
<!-- this repo has no ipv6 so keep that in mind -->
|
||||
<repository>
|
||||
<id>maxhenkel-repo</id>
|
||||
<url>https://maven.maxhenkel.de/repository/public</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.21.1-R0.1-SNAPSHOT</version>
|
||||
<version>${project.spigot.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>${project.spigot.version}</version>
|
||||
<classifier>remapped-mojang</classifier>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>5.3.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.maxhenkel.voicechat</groupId>
|
||||
<artifactId>voicechat-api</artifactId>
|
||||
<version>2.5.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -81,11 +139,5 @@
|
|||
<version>24.1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<version>5.3.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -3,11 +3,14 @@ package eu.m724.tweaks;
|
|||
import eu.m724.tweaks.chat.ChatCommands;
|
||||
import eu.m724.tweaks.chat.ChatManager;
|
||||
import eu.m724.tweaks.door.DoorListener;
|
||||
import eu.m724.tweaks.motd.MotdListener;
|
||||
import eu.m724.tweaks.ping.F3NameListener;
|
||||
import eu.m724.tweaks.ping.PingChecker;
|
||||
import eu.m724.tweaks.ping.PingCommands;
|
||||
import eu.m724.tweaks.player.MusicPlayer;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class TweaksPlugin extends JavaPlugin {
|
||||
|
@ -26,5 +29,18 @@ public class TweaksPlugin extends JavaPlugin {
|
|||
new PingChecker(this).init();
|
||||
Objects.requireNonNull(getCommand("ping")).setExecutor(new PingCommands());
|
||||
Objects.requireNonNull(getCommand("dkick")).setExecutor(new PingCommands());
|
||||
|
||||
if (getServer().getPluginManager().getPlugin("voicechat") != null) {
|
||||
new MusicPlayer(this).init();
|
||||
} else {
|
||||
getLogger().warning("To use voice extensions, install \"Simple Voice Chat\"");
|
||||
}
|
||||
|
||||
try {
|
||||
new MotdListener("example").init(this);
|
||||
} catch (IOException e) {
|
||||
getLogger().severe("Failed to initialize MOTD extension");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
87
src/main/java/eu/m724/tweaks/motd/MotdListener.java
Normal file
87
src/main/java/eu/m724/tweaks/motd/MotdListener.java
Normal file
|
@ -0,0 +1,87 @@
|
|||
package eu.m724.tweaks.motd;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.events.*;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.google.gson.JsonElement;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.status.ServerStatus;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class MotdListener {
|
||||
private final String motdSetName;
|
||||
|
||||
private Component[] motds;
|
||||
|
||||
public MotdListener(String motdSetName) {
|
||||
this.motdSetName = motdSetName;
|
||||
}
|
||||
|
||||
public void init(Plugin plugin) throws IOException {
|
||||
File motdSetsFile = new File(plugin.getDataFolder() + "/motd sets/" + motdSetName + ".txt");
|
||||
|
||||
// if the directory didn't exist create example motd sets
|
||||
if (motdSetsFile.getParentFile().mkdirs()) {
|
||||
plugin.saveResource("motd sets/" + motdSetName + ".txt", true);
|
||||
}
|
||||
|
||||
String fileContent = Files.readString(motdSetsFile.toPath());
|
||||
// MOTDs are split with an empty line
|
||||
motds = Arrays.stream(fileContent.split("\n\n"))
|
||||
.map(s -> {
|
||||
JsonElement json = ComponentSerializer.toJson(TextComponent.fromLegacy(s.strip()));
|
||||
return Component.Serializer.fromJson(json, RegistryAccess.EMPTY);
|
||||
})
|
||||
.toArray(Component[]::new);
|
||||
|
||||
plugin.getLogger().info("Loaded %d MOTDs".formatted(motds.length));
|
||||
|
||||
registerListener(plugin);
|
||||
}
|
||||
|
||||
private void registerListener(Plugin plugin) {
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(
|
||||
plugin,
|
||||
ListenerPriority.NORMAL,
|
||||
PacketType.Status.Server.SERVER_INFO
|
||||
) {
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
PacketContainer packet = event.getPacket();
|
||||
|
||||
Component motd = motds[ThreadLocalRandom.current().nextInt(motds.length)];
|
||||
|
||||
ServerStatus serverStatus = (ServerStatus) packet.getStructures().read(0).getHandle();
|
||||
|
||||
/* this:
|
||||
* removes server mod prefix (Paper, Spigot, any brand)
|
||||
* hides players
|
||||
*/
|
||||
ServerStatus newStatus = new ServerStatus(
|
||||
motd,
|
||||
Optional.empty(),
|
||||
Optional.of(new ServerStatus.Version(
|
||||
SharedConstants.getCurrentVersion().getName(),
|
||||
SharedConstants.getProtocolVersion()
|
||||
)),
|
||||
serverStatus.favicon(),
|
||||
false
|
||||
);
|
||||
|
||||
packet.getStructures().write(0, new InternalStructure(newStatus, new StructureModifier<>(ServerStatus.class)));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -4,26 +4,16 @@ import com.comphenix.protocol.PacketType;
|
|||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.events.*;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import net.minecraft.network.protocol.common.custom.BrandPayload;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class F3NameListener {
|
||||
private final Plugin plugin;
|
||||
private final Class<?> brandPayloadClass;
|
||||
private final Constructor<?> brandPayloadConstructor;
|
||||
|
||||
public F3NameListener(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
try {
|
||||
this.brandPayloadClass = Class.forName("net.minecraft.network.protocol.common.custom.BrandPayload");
|
||||
this.brandPayloadConstructor = brandPayloadClass.getConstructor(String.class);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException e) {
|
||||
throw new BrandPayloadReflectionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void init() {
|
||||
|
@ -57,34 +47,27 @@ public class F3NameListener {
|
|||
) {
|
||||
@Override
|
||||
public void onPacketSending(PacketEvent event) {
|
||||
try {
|
||||
PacketContainer packet = event.getPacket();
|
||||
Object brandPayload = brandPayloadConstructor.newInstance("wait");
|
||||
InternalStructure structure = new InternalStructure(brandPayload, new StructureModifier<>(brandPayloadClass));
|
||||
|
||||
InternalStructure structure = new InternalStructure(
|
||||
new BrandPayload("wait"),
|
||||
new StructureModifier<>(BrandPayload.class)
|
||||
);
|
||||
|
||||
packet.getStructures().write(0, structure);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new BrandPayloadReflectionException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void changeBrand(Player player, String brand) {
|
||||
PacketContainer packet = new PacketContainer(PacketType.Play.Server.CUSTOM_PAYLOAD);
|
||||
Object brandPayload;
|
||||
try {
|
||||
brandPayload = brandPayloadConstructor.newInstance(brand);
|
||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||
throw new BrandPayloadReflectionException(e);
|
||||
}
|
||||
InternalStructure structure = new InternalStructure(brandPayload, new StructureModifier<>(brandPayloadClass));
|
||||
|
||||
InternalStructure structure = new InternalStructure(
|
||||
new BrandPayload(brand),
|
||||
new StructureModifier<>(BrandPayload.class)
|
||||
);
|
||||
|
||||
packet.getStructures().write(0, structure);
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet);
|
||||
}
|
||||
|
||||
public static class BrandPayloadReflectionException extends RuntimeException {
|
||||
public BrandPayloadReflectionException(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
70
src/main/java/eu/m724/tweaks/player/MusicPlayer.java
Normal file
70
src/main/java/eu/m724/tweaks/player/MusicPlayer.java
Normal file
|
@ -0,0 +1,70 @@
|
|||
package eu.m724.tweaks.player;
|
||||
|
||||
import de.maxhenkel.voicechat.api.BukkitVoicechatService;
|
||||
import de.maxhenkel.voicechat.api.VoicechatServerApi;
|
||||
import de.maxhenkel.voicechat.api.VolumeCategory;
|
||||
import de.maxhenkel.voicechat.api.audiochannel.AudioPlayer;
|
||||
import de.maxhenkel.voicechat.api.audiochannel.EntityAudioChannel;
|
||||
import de.maxhenkel.voicechat.api.opus.OpusEncoderMode;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
import javax.sound.sampled.AudioSystem;
|
||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MusicPlayer {
|
||||
private static final String PLAYER_CATEGORY = "music_player";
|
||||
|
||||
private VoicechatServerApi voicechat = null;
|
||||
|
||||
private final Plugin plugin;
|
||||
|
||||
public MusicPlayer(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
BukkitVoicechatService service = plugin.getServer().getServicesManager().load(BukkitVoicechatService.class);
|
||||
service.registerPlugin(new MyVoicechatPlugin(this));
|
||||
}
|
||||
|
||||
void unlock(VoicechatServerApi voicechat) {
|
||||
VolumeCategory category = voicechat.volumeCategoryBuilder()
|
||||
.setId(PLAYER_CATEGORY)
|
||||
.setName("Music players")
|
||||
.build();
|
||||
|
||||
voicechat.registerVolumeCategory(category);
|
||||
|
||||
this.voicechat = voicechat;
|
||||
}
|
||||
|
||||
public void create(Player player) {
|
||||
UUID channelID = UUID.randomUUID();
|
||||
EntityAudioChannel channel = voicechat.createEntityAudioChannel(channelID, voicechat.fromEntity(player));
|
||||
|
||||
channel.setCategory(PLAYER_CATEGORY);
|
||||
channel.setDistance(10);
|
||||
|
||||
short[] arr;
|
||||
try {
|
||||
AudioInputStream audio = AudioSystem.getAudioInputStream(plugin.getResource("music.flac"));
|
||||
int samples = (int) (audio.available() / audio.getFrameLength());
|
||||
arr = new short[samples];
|
||||
for (int i=0; i<audio.available(); i++) {
|
||||
|
||||
}
|
||||
} catch (UnsupportedAudioFileException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
AudioPlayer audioPlayer = voicechat.createAudioPlayer(channel, voicechat.createEncoder(OpusEncoderMode.AUDIO), arr);
|
||||
audioPlayer.startPlaying();
|
||||
|
||||
}
|
||||
}
|
35
src/main/java/eu/m724/tweaks/player/MyVoicechatPlugin.java
Normal file
35
src/main/java/eu/m724/tweaks/player/MyVoicechatPlugin.java
Normal file
|
@ -0,0 +1,35 @@
|
|||
package eu.m724.tweaks.player;
|
||||
|
||||
import de.maxhenkel.voicechat.api.VoicechatApi;
|
||||
import de.maxhenkel.voicechat.api.VoicechatPlugin;
|
||||
import de.maxhenkel.voicechat.api.VoicechatServerApi;
|
||||
import de.maxhenkel.voicechat.api.events.EventRegistration;
|
||||
import de.maxhenkel.voicechat.api.events.VoicechatServerStartedEvent;
|
||||
|
||||
public class MyVoicechatPlugin implements VoicechatPlugin {
|
||||
private final MusicPlayer musicPlayer;
|
||||
|
||||
MyVoicechatPlugin(MusicPlayer musicPlayer) {
|
||||
this.musicPlayer = musicPlayer;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPluginId() {
|
||||
return "tweaks724";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(VoicechatApi api) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerEvents(EventRegistration registration) {
|
||||
registration.registerEvent(VoicechatServerStartedEvent.class, this::onServerStarted);
|
||||
}
|
||||
|
||||
public void onServerStarted(VoicechatServerStartedEvent event) {
|
||||
VoicechatServerApi api = event.getVoicechat();
|
||||
musicPlayer.unlock(api);
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ version: ${project.version}
|
|||
main: eu.m724.tweaks.TweaksPlugin
|
||||
api-version: 1.21.1
|
||||
depend: [ProtocolLib]
|
||||
softdepend: [voicechat]
|
||||
|
||||
commands:
|
||||
chat:
|
||||
|
|
Loading…
Reference in a new issue