This commit is contained in:
YuTian 2024-08-03 10:05:51 +08:00
parent 2a715306d3
commit 7ad3076315
81 changed files with 3302 additions and 3233 deletions

View File

@ -1,6 +1,6 @@
<component name="ArtifactManager"> <component name="ArtifactManager">
<artifact type="jar" name="McLiveAPI"> <artifact type="jar" name="McLiveAPI">
<output-path>$PROJECT_DIR$/out/artifacts/McLiveAPI</output-path> <output-path>$PROJECT_DIR$/../../../Desktop/1.18.1s/plugins</output-path>
<root id="archive" name="McLiveAPI.jar"> <root id="archive" name="McLiveAPI.jar">
<element id="module-output" name="McLiveAPI" /> <element id="module-output" name="McLiveAPI" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/fastjson-2.0.43.jar" path-in-jar="/" /> <element id="extracted-dir" path="$PROJECT_DIR$/lib/fastjson-2.0.43.jar" path-in-jar="/" />

View File

@ -6,6 +6,21 @@
<option name="name" value="Central Repository" /> <option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" /> <option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository> </remote-repository>
<remote-repository>
<option name="id" value="sonatype" />
<option name="name" value="sonatype" />
<option name="url" value="https://oss.sonatype.org/content/groups/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="public-rpg" />
<option name="name" value="public-rpg" />
<option name="url" value="https://repo.aurora-pixels.com/repository/public-rpg/" />
</remote-repository>
<remote-repository>
<option name="id" value="papermc-repo" />
<option name="name" value="papermc-repo" />
<option name="url" value="https://repo.papermc.io/repository/maven-public/" />
</remote-repository>
<remote-repository> <remote-repository>
<option name="id" value="central" /> <option name="id" value="central" />
<option name="name" value="Maven Central repository" /> <option name="name" value="Maven Central repository" />

View File

@ -4,8 +4,10 @@
<facet type="minecraft" name="Minecraft"> <facet type="minecraft" name="Minecraft">
<configuration> <configuration>
<autoDetectTypes> <autoDetectTypes>
<platformType>SPIGOT</platformType> <platformType>PAPER</platformType>
<platformType>ADVENTURE</platformType>
</autoDetectTypes> </autoDetectTypes>
<projectReimportVersion>1</projectReimportVersion>
</configuration> </configuration>
</facet> </facet>
</component> </component>

Binary file not shown.

32
pom.xml
View File

@ -1,4 +1,4 @@
<?xml c="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
@ -49,4 +49,34 @@
</resources> </resources>
</build> </build>
<repositories>
<repository>
<id>papermc-repo</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
<repository>
<id>public-rpg</id>
<url>https://repo.aurora-pixels.com/repository/public-rpg/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.18.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cn.hamster3.cdapi</groupId>
<artifactId>CDTimeAPI</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project> </project>

View File

@ -1,7 +1,5 @@
package com.io.yutian.livemutually.liveroom; package com.io.yutian.livemutually.liveroom;
import org.bukkit.Bukkit;
import java.util.Objects; import java.util.Objects;
import java.util.function.Consumer; import java.util.function.Consumer;

View File

@ -0,0 +1,242 @@
package com.io.yutian.livemutually.manager;
import com.io.yutian.mclive.Main;
import com.io.yutian.mclive.data.database.SqlManager;
import com.io.yutian.mclive.util.ConfigYml;
import com.io.yutian.mclive.util.SqlUtil;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
public class GiftManager {
private double totalMoney;
private LinkedHashMap<String, Integer> giftMap = new LinkedHashMap<>();
private SqlUtil sqlUtil;
private SqlManager sqlManager;
public GiftManager() {
totalMoney = 0;
giftMap.put("小心心", 1);
giftMap.put("人气票", 1);
giftMap.put("闪耀星辰", 1);
giftMap.put("加油鸭", 1);
giftMap.put("比心兔兔", 1);
giftMap.put("热气球", 1);
giftMap.put("爱你哟", 1);
giftMap.put("天鹅之梦", 1);
giftMap.put("Thuglife", 1);
giftMap.put("粘人小狗", 1);
giftMap.put("粉丝团灯牌", 1);
giftMap.put("大啤酒", 2);
giftMap.put("玫瑰", 1);
giftMap.put("抖音", 1);
giftMap.put("称心如意", 1);
giftMap.put("你最好看", 2);
giftMap.put("助力票", 1);
giftMap.put("荣耀擂鼓", 99);
giftMap.put("宠粉季", 1);
giftMap.put("兔耳朵", 99);
giftMap.put("游戏手柄", 99);
giftMap.put("冰镇西瓜", 99);
giftMap.put("为你闪耀", 9);
giftMap.put("棒棒糖", 9);
giftMap.put("鲜花", 10);
giftMap.put("亲吻", 99);
giftMap.put("跑车", 1200);
giftMap.put("礼花筒", 199);
giftMap.put("捏捏小脸", 99);
giftMap.put("鹿仙子", 99);
giftMap.put("夏威夷花环", 99);
giftMap.put("爱的纸鹤", 99);
giftMap.put("送你花花", 49);
giftMap.put("女神花环", 99);
giftMap.put("鱼你一起", 99);
giftMap.put("真爱玫瑰", 366);
giftMap.put("为你举牌", 199);
giftMap.put("龙抬头", 99);
giftMap.put("花开烂漫", 466);
giftMap.put("比心", 199);
giftMap.put("真的爱你", 520);
giftMap.put("万象烟花", 688);
giftMap.put("私人飞机", 3000);
giftMap.put("浪漫烟花", 599);
giftMap.put("闪亮登场", 460);
giftMap.put("多喝热水", 126);
giftMap.put("一点心意", 266);
giftMap.put("荧光棒", 99);
giftMap.put("娶你回家", 599);
giftMap.put("掌上明珠", 888);
giftMap.put("摧残舞台", 899);
giftMap.put("星星点灯", 268);
giftMap.put("一束花开", 366);
giftMap.put("小傻猪", 299);
giftMap.put("环球旅行车", 650);
giftMap.put("爱的守护", 299);
giftMap.put("好运莲莲鸭", 299);
giftMap.put("日出相伴", 726);
giftMap.put("永生花", 520);
giftMap.put("纸短情长", 921);
giftMap.put("直升机", 2999);
giftMap.put("蝶·连理枝", 280);
giftMap.put("爱情树下", 599);
giftMap.put("灵龙现世", 600);
giftMap.put("爱心煎蛋", 99);
giftMap.put("夏日回忆", 1000);
giftMap.put("抖音1号", 10001);
giftMap.put("繁花秘语", 1314);
giftMap.put("ONE礼挑一", 299);
giftMap.put("重拳出击", 199);
giftMap.put("花落长亭", 1588);
giftMap.put("浪漫恋人", 1999);
giftMap.put("花海泛舟", 2800);
giftMap.put("豪华邮轮", 6000);
giftMap.put("环游世界", 3000);
giftMap.put("蝶·书中情", 750);
giftMap.put("带你去海边", 4500);
giftMap.put("蜜蜂叮叮", 1000);
giftMap.put("奇幻八音盒", 2399);
giftMap.put("光之祝福", 1999);
giftMap.put("消暑罐头车", 1500);
giftMap.put("月色山茶花", 1999);
giftMap.put("为你而来", 1688);
giftMap.put("点亮孤单", 1800);
giftMap.put("浪漫营地", 1699);
giftMap.put("薰衣草庄园", 3300);
giftMap.put("红墙白雪", 1688);
giftMap.put("华灯初上", 5000);
giftMap.put("嘉年华", 30000);
giftMap.put("单车恋人", 1899);
giftMap.put("为爱启航", 10001);
giftMap.put("镜中奇缘", 1500);
giftMap.put("仲夏夜之梦", 8999);
giftMap.put("龙珠纳福", 2388);
giftMap.put("蝶·比翼鸟", 1700);
giftMap.put("无畏守护", 10168);
giftMap.put("壁上飞仙", 4999);
giftMap.put("海上生明月", 4166);
giftMap.put("铁甲柔情", 3800);
giftMap.put("心动丘比特", 4321);
giftMap.put("变形战车", 5500);
giftMap.put("抖音飞艇", 20000);
giftMap.put("冰冻战车", 3000);
giftMap.put("星际玫瑰", 7500);
giftMap.put("奏响人生", 3666);
giftMap.put("摩天大厦", 8222);
giftMap.put("传送门", 2999);
giftMap.put("云中秘境", 13140);
giftMap.put("火龙爆发", 5000);
giftMap.put("福佑万家", 4888);
giftMap.put("天空之镜", 6399);
giftMap.put("情定三生", 9666);
giftMap.put("月下瀑布", 6666);
giftMap.put("金鳞化龙", 9000);
giftMap.put("蝶·化蝶飞", 10999);
giftMap.put("无尽浪漫", 19999);
giftMap.put("云霄大厦", 7888);
giftMap.put("梦幻城堡", 28888);
giftMap.put("真爱永恒", 8999);
giftMap.put("跨时空之恋", 9000);
giftMap.put("炫彩射击", 1888);
giftMap.put("一路有你", 17999);
giftMap.put("浪漫马车", 28888);
giftMap.put("蝶·寄相思", 6800);
giftMap.put("梦回紫禁城", 8666);
giftMap.put("小纸条", 399);
giftMap.put("如意锦囊", 99);
giftMap.put("星光瓶", 900);
giftMap.put("一直陪伴你", 520);
giftMap.put("动次打次", 2999);
giftMap.put("宇宙之心", 18888);
}
public List<String> getGiftNameList() {
return new ArrayList<>(giftMap.keySet());
}
public SqlUtil getSqlUtil() {
return sqlUtil;
}
public SqlManager getSqlManager() {
return sqlManager;
}
public void LinkMySqlData() {
String SQL_Host = "gz-cdb-r9koldtt.sql.tencentcdb.com";
String SQL_Port = "29320";
String SQL_Users = "root";
String SQL_Password = "Pixel@123456";
String SQL_Database = "mclivedata";
sqlManager = new SqlManager();
sqlUtil = new SqlUtil(SQL_Host, SQL_Port, SQL_Database, SQL_Users, SQL_Password);
sqlManager.createTable();
}
public int getGiftMoney(String giftName) {
if (giftMap.get(giftName) == null) {
return 1;
}
return giftMap.get(giftName);
}
public double getTotalMoney() {
return totalMoney;
}
public void defaultTotalMoney() {
if (this.totalMoney <= 0) {
for (Player player : Bukkit.getOnlinePlayers()) {
String name = player.getName();
if (Main.configYml.getRoomId(name) == null) {
return;
}
String tiktok = Main.configYml.getRoomId(name);
this.totalMoney = sqlManager.getZhuboIncome(tiktok) * 10;
}
}
}
public void addTotalMoney(String name, int money) {
if (this.totalMoney <= 0) {
if (Main.configYml.getRoomId(name) == null) {
return;
}
String tiktok = Main.configYml.getRoomId(name);
this.totalMoney = sqlManager.getZhuboIncome(tiktok) * 10;
}
if (money >= 5000) {
SaveZhuboData(name);
}
this.totalMoney += money;
}
public void addTotalMoney(String name, int money, long amount) {
if (this.totalMoney <= 0) {
if (Main.configYml.getRoomId(name) == null) {
return;
}
String tiktok = Main.configYml.getRoomId(name);
this.totalMoney = sqlManager.getZhuboIncome(tiktok) * 10;
}
int newMoney = (int) (money * amount);
if (newMoney >= 5000) {
SaveZhuboData(name);
}
this.totalMoney += newMoney;
}
public void SaveZhuboData(String name) {
if (Main.configYml.getRoomId(name) == null) {
return;
}
String tiktok = Main.configYml.getRoomId(name);
if (ConfigYml.mysqlState) {
sqlManager.SavePlayerData(tiktok);
}
}
}

View File

@ -1,21 +1,17 @@
package com.io.yutian.livemutually.manager; package com.io.yutian.livemutually.manager;
import cn.hamster3.cdapi.CDTimeAPI;
import com.io.yutian.mclive.*;
import com.io.yutian.pixelliveplugin.PixelLiveAPI; import com.io.yutian.pixelliveplugin.PixelLiveAPI;
import com.io.yutian.verify.AESUtil;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.regex.Pattern;
public class KSLiveRoomManager { public class KSLiveRoomManager {
public static List<Player> livepluginList = new ArrayList<>(); private static List<Player> players = new ArrayList<>();
public static boolean isConnected(Player player) { public static boolean isConnected(Player player) {
if(livepluginList.contains(player)){ if (players.contains(player)) {
return true; return true;
} }
return false; return false;
@ -25,9 +21,13 @@ public class KSLiveRoomManager {
if (!isConnected(player)) { if (!isConnected(player)) {
return; return;
} }
livepluginList.remove(player); players.remove(player);
PixelLiveAPI.disconnect(player); PixelLiveAPI.disconnect(player);
player.sendMessage("§c[系统]§b已断开直播间连接..."); player.sendMessage("§c[系统]§b已断开直播间连接...");
} }
public static List<Player> getPlayers() {
return players;
}
} }

View File

@ -0,0 +1,115 @@
package com.io.yutian.livemutually.manager;
import com.io.yutian.mclive.Main;
import com.io.yutian.mclive.data.UserResourceData;
import com.io.yutian.pixelengine.api.EngineAPI;
import com.io.yutian.pixelengine.api.util.ImageUtil;
import json.JSONObject;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
public class RankManager {
private static List<String> topCache = new ArrayList<>();
private static Map<String, Long> userDatas = new HashMap<>();
public static void addUserAmount(String userName, long score) {
if (userName == null || userName.isEmpty() || userName.length() == 0) {
return;
}
long amount = userDatas.getOrDefault(userName, score);
userDatas.put(userName, amount + score);
Bukkit.getScheduler().runTaskAsynchronously(Main.plugin, RankManager::update);
save();
}
public static void update() {
List<String> tops = userDatas.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.limit(3)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
if (topCache.isEmpty() || !topCache.equals(tops)) {
topCache = tops;
for (int i = 0; i < 3; i++) {
if (i >= tops.size()) {
return;
}
String name = tops.get(i);
UserResourceData userResourceData = UserManager.getUserResourceData(name);
if (userResourceData != null) {
int finalI = i;
String base64 = ImageUtil.getCacheImageBase64(userResourceData.getNickName(), userResourceData.getAvatarThumbUrl(), (newBase64) -> {
for (Player player : Bukkit.getOnlinePlayers()) {
EngineAPI.getRankAPI().setRankData(player, finalI + 1, newBase64, userResourceData.getLevel());
}
});
for (Player player : Bukkit.getOnlinePlayers()) {
EngineAPI.getRankAPI().setRankData(player, i + 1, base64, userResourceData.getLevel());
}
}
}
}
}
public static long getUserAmount(String userName) {
return userDatas.getOrDefault(userName, 0L);
}
public static void save() {
File file = new File(Main.plugin.getDataFolder(), "rank.yml");
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
FileConfiguration config = YamlConfiguration.loadConfiguration(file);
for (Map.Entry<String, Long> entry : userDatas.entrySet()) {
String key = entry.getKey();
if (key == null || key.isEmpty() || key.length() == 0) {
continue;
}
try {
config.set(key, entry.getValue());
} catch (Exception e) {
}
}
try {
config.save(file);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void load() {
File file = new File(Main.plugin.getDataFolder(), "rank.yml");
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
FileConfiguration config = YamlConfiguration.loadConfiguration(file);
for (String key : config.getKeys(false)) {
userDatas.put(key, config.getLong(key));
}
}
public static void clear() {
File file = new File(Main.plugin.getDataFolder(), "rank.yml");
file.delete();
userDatas.clear();
}
}

View File

@ -1,39 +0,0 @@
package com.io.yutian.livemutually.manager;
import java.util.HashMap;
public class UserData {
private String userName;
// 礼物 礼物数据
private HashMap<String,GiftData> giftData = new HashMap<>();
public UserData(String userName){
this.userName = userName;
this.giftData = new HashMap<>();
}
public String getUserName() {
return userName;
}
// 判断本次赠送礼物是否已送过
public boolean isExitGift(String giftName){
if(giftData.get(giftName) != null){
return true;
}
return false;
}
public GiftData getGiftsData(String giftName){
if(giftData.get(giftName) != null){
return giftData.get(giftName);
}
return null;
}
public void createGiftsData(String giftName,long giftAmount){
long sendTime = System.currentTimeMillis();
giftData.put(giftName,new GiftData(giftName,giftAmount,sendTime));
}
}

View File

@ -0,0 +1,20 @@
package com.io.yutian.livemutually.manager;
import com.io.yutian.mclive.data.UserResourceData;
import java.util.HashMap;
import java.util.Map;
public class UserManager {
private static Map<String, UserResourceData> userResourceDataMap = new HashMap<>();
public static void setUserResourceData(String userName, UserResourceData userResourceData) {
userResourceDataMap.put(userName, userResourceData);
}
public static UserResourceData getUserResourceData(String userName) {
return userResourceDataMap.get(userName);
}
}

View File

@ -15,19 +15,19 @@ public class KSAPILiveRoomWatcher extends LiveRoomWatcher {
public KSAPILiveRoomWatcher(Player player) { public KSAPILiveRoomWatcher(Player player) {
this.player = player; this.player = player;
onChat(chat -> { onChat(chat -> {
Bukkit.getScheduler().runTask(Main.plugin, ()-> { Bukkit.getScheduler().runTask(Main.plugin, () -> {
LiveChatEvents event = new LiveChatEvents(player, chat.user(), chat.content()); LiveChatEvents event = new LiveChatEvents(player, chat.user(), chat.content());
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
}); });
}); });
onUser(user -> { onUser(user -> {
Bukkit.getScheduler().runTask(Main.plugin, ()-> { Bukkit.getScheduler().runTask(Main.plugin, () -> {
LiveEnterEvents event = new LiveEnterEvents(player, user); LiveEnterEvents event = new LiveEnterEvents(player, user);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
}); });
}); });
onLike(like -> { onLike(like -> {
Bukkit.getScheduler().runTask(Main.plugin, ()-> { Bukkit.getScheduler().runTask(Main.plugin, () -> {
LiveLikeEvents event = new LiveLikeEvents(player, like.user(), like.count()); LiveLikeEvents event = new LiveLikeEvents(player, like.user(), like.count());
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
}); });

View File

@ -1,7 +1,9 @@
package com.io.yutian.mclive; package com.io.yutian.mclive;
import com.io.yutian.livemutually.manager.KSLiveRoomManager; import com.io.yutian.livemutually.manager.KSLiveRoomManager;
import com.io.yutian.mclive.data.GiftManage; import com.io.yutian.livemutually.manager.GiftManager;
import com.io.yutian.livemutually.manager.RankManager;
import com.io.yutian.livemutually.manager.UserManager;
import com.io.yutian.mclive.event.ZhuboAPI; import com.io.yutian.mclive.event.ZhuboAPI;
import com.io.yutian.mclive.listener.JoinGameRoom; import com.io.yutian.mclive.listener.JoinGameRoom;
import com.io.yutian.mclive.listener.LiveAdminGui; import com.io.yutian.mclive.listener.LiveAdminGui;
@ -9,13 +11,14 @@ import com.io.yutian.mclive.listener.SoundsMenu;
import com.io.yutian.mclive.live.LiveEvent; import com.io.yutian.mclive.live.LiveEvent;
import com.io.yutian.mclive.live.ModEvent; import com.io.yutian.mclive.live.ModEvent;
import com.io.yutian.mclive.util.ConfigYml; import com.io.yutian.mclive.util.ConfigYml;
import com.io.yutian.pixelliveplugin.PixelLiveAPI;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.*; import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
@ -30,45 +33,10 @@ public class Main extends JavaPlugin {
public static Main plugin; public static Main plugin;
public static boolean check_plugin = false; public static boolean check_plugin = false;
public static ConfigYml configYml; public static ConfigYml configYml;
public static GiftManage giftManage; public static GiftManager giftManager;
public static boolean giftStatistics = true; public static boolean giftStatistics = true;
@Override public static void addSoundKeyList() {
public void onEnable() {
plugin = this;
SendPluginsAuthorMessage(Bukkit.getConsoleSender());
configYml = new ConfigYml(getConfig());
if (giftStatistics){
giftManage = new GiftManage();
giftManage.LinkMySqlData();
}
addSoundKeyList();
getServer().getPluginManager().registerEvents(new LiveAdminGui(),this);
getServer().getPluginManager().registerEvents(new JoinGameRoom(),this);
getServer().getPluginManager().registerEvents(new ModEvent(),this);
getServer().getPluginManager().registerEvents(new LiveEvent(configYml),this);
getServer().getPluginManager().registerEvents(new SoundsMenu(),this);
Bukkit.getConsoleSender().sendMessage("§b[整蛊MC直播] §7当前版本: §ev"+plugin.getDescription().getVersion());
Plugin plugin = getServer().getPluginManager().getPlugin(configYml.getGameMode());
if (plugin != null) {
check_plugin = true;
Bukkit.getConsoleSender().sendMessage("§b[整蛊MC直播] §a已激活游戏模式");
if(giftStatistics) {
Bukkit.getScheduler().runTaskTimerAsynchronously(this, new Runnable() {
@Override
public void run() {
for (Player player : Bukkit.getOnlinePlayers()) {
giftManage.SaveZhuboData(player.getName());
}
}
}, 0L, 24000L);
}
} else {
Bukkit.getConsoleSender().sendMessage("§b[整蛊MC直播] §c未检测到§a<"+configYml.getGameMode()+">§c游戏插件.");
}
}
public static void addSoundKeyList(){
List<String> stringList = new ArrayList<>(); List<String> stringList = new ArrayList<>();
stringList.add("youbom"); stringList.add("youbom");
stringList.add("oi"); stringList.add("oi");
@ -121,11 +89,91 @@ public class Main extends JavaPlugin {
SoundsMenu.soundList.addAll(stringList); SoundsMenu.soundList.addAll(stringList);
} }
public static void SendPluginsAuthorMessage(CommandSender sender) {
sender.sendMessage(" ");
sender.sendMessage("§b ██ ████");
sender.sendMessage("§b ██");
sender.sendMessage("§b██░███▒ ████ ███ ███ ░████▒ ██");
sender.sendMessage("§b███████▒ ████ ██▒▒██ ░██████▒ ██");
sender.sendMessage("§b███ ███ ██ ▒████▒ ██▒ ▒██ ██");
sender.sendMessage("§b██░ ░██ ██ ████ ████████ ██");
sender.sendMessage("§b██ ██ ██ ▒██▒ ████████ ██");
sender.sendMessage("§b██░ ░██ ██ ████ ██ ██");
sender.sendMessage("§b███ ███ ██ ▒████▒ ███░ ▒█ ██▒");
sender.sendMessage("§b███████▒ ████████ ██▒▒██ ░███████ █████");
sender.sendMessage("§b██░███▒ ████████ ███ ███ ░█████▒ ░████");
sender.sendMessage("§b██");
sender.sendMessage("§b█ 弹幕互动引擎 由极光像素工作室提供技术支持!!");
sender.sendMessage("§b█ 如有使用问题可联系售后: §d" + getAuthorFile().getString("author"));
sender.sendMessage("" + getAuthorFile().getString("linemessage"));
}
public static FileConfiguration getAuthorFile() {
File ShopMenufile = new File("plugins/PluginMetrics", "config.yml");
return YamlConfiguration.loadConfiguration(ShopMenufile);
}
public static String HideName(String audience) {
if (audience.length() <= 2) {
return "**";
}
// 获取第一个和第二个字符
char firstChar = audience.charAt(0);
char lastChar = audience.charAt(audience.length() - 1);
// 构建屏蔽后的字符串
StringBuilder maskedString = new StringBuilder();
for (int i = 1; i < audience.length() - 1; i++) {
maskedString.append('*');
}
return String.valueOf(firstChar) + maskedString + lastChar;
}
public static String getMinecraftVersion() {
String packageName = Bukkit.getServer().getClass().getPackage().getName();
String version = packageName.substring(packageName.lastIndexOf('.') + 1);
return version;
}
@Override
public void onEnable() {
plugin = this;
SendPluginsAuthorMessage(Bukkit.getConsoleSender());
configYml = new ConfigYml(getConfig());
if (giftStatistics) {
giftManager = new GiftManager();
giftManager.LinkMySqlData();
}
addSoundKeyList();
getServer().getPluginManager().registerEvents(new LiveAdminGui(), this);
getServer().getPluginManager().registerEvents(new JoinGameRoom(), this);
getServer().getPluginManager().registerEvents(new ModEvent(), this);
getServer().getPluginManager().registerEvents(new LiveEvent(configYml), this);
getServer().getPluginManager().registerEvents(new SoundsMenu(), this);
Bukkit.getConsoleSender().sendMessage("§b[整蛊MC直播] §7当前版本: §ev" + plugin.getDescription().getVersion());
Plugin plugin = getServer().getPluginManager().getPlugin(configYml.getGameMode());
check_plugin = true;
if (plugin != null) {
RankManager.load();
check_plugin = true;
Bukkit.getConsoleSender().sendMessage("§b[整蛊MC直播] §a已激活游戏模式");
if (giftStatistics) {
Bukkit.getScheduler().runTaskTimerAsynchronously(this, () -> {
for (Player player : Bukkit.getOnlinePlayers()) {
giftManager.SaveZhuboData(player.getName());
}
}, 0L, 24000L);
}
} else {
Bukkit.getConsoleSender().sendMessage("§b[整蛊MC直播] §c未检测到§a<" + configYml.getGameMode() + ">§c游戏插件.");
}
}
@Override @Override
public void onDisable() { public void onDisable() {
if(giftStatistics && ConfigYml.mysqlState) { if (giftStatistics && ConfigYml.mysqlState) {
for (Player player : Bukkit.getOnlinePlayers()) { for (Player player : Bukkit.getOnlinePlayers()) {
giftManage.SaveZhuboData(player.getName()); giftManager.SaveZhuboData(player.getName());
} }
} }
} }
@ -133,7 +181,7 @@ public class Main extends JavaPlugin {
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String Command, String[] args) { public boolean onCommand(CommandSender sender, Command command, String Command, String[] args) {
if (Command.equalsIgnoreCase("sounds")) { if (Command.equalsIgnoreCase("sounds")) {
SoundsMenu.OpenGui((Player) sender,1); SoundsMenu.OpenGui((Player) sender, 1);
} }
if (Command.equalsIgnoreCase("mclive")) { if (Command.equalsIgnoreCase("mclive")) {
if (args.length == 0) { if (args.length == 0) {
@ -151,14 +199,20 @@ public class Main extends JavaPlugin {
sender.sendMessage(""); sender.sendMessage("");
return true; return true;
} }
if (args.length == 1 && args[0].equalsIgnoreCase("test")) {
Player player = (Player) sender;
PixelLiveAPI.connect(player, "127.0.0.1", 9018);
return true;
}
if (args.length == 1 && args[0].equalsIgnoreCase("reload")) { if (args.length == 1 && args[0].equalsIgnoreCase("reload")) {
Main.configYml.ReloadConfig(); Main.configYml.ReloadConfig();
sender.sendMessage("§c[系统]§a配置文件已重载"); sender.sendMessage("§c[系统]§a配置文件已重载");
return true; return true;
} }
if (args.length == 1 && args[0].equalsIgnoreCase("save")) { if (args.length == 1 && args[0].equalsIgnoreCase("save")) {
for (Player player : Bukkit.getOnlinePlayers()){ for (Player player : Bukkit.getOnlinePlayers()) {
giftManage.SaveZhuboData(player.getName()); giftManager.SaveZhuboData(player.getName());
} }
sender.sendMessage("§c[系统]§a数据已提交至云数据库."); sender.sendMessage("§c[系统]§a数据已提交至云数据库.");
return true; return true;
@ -177,7 +231,7 @@ public class Main extends JavaPlugin {
} }
if (args.length == 1 && args[0].equalsIgnoreCase("stop")) { if (args.length == 1 && args[0].equalsIgnoreCase("stop")) {
ZhuboAPI.wsRoomIdSame.clear(); ZhuboAPI.wsRoomIdSame.clear();
for (Player player : KSLiveRoomManager.livepluginList) { for (Player player : KSLiveRoomManager.getPlayers()) {
KSLiveRoomManager.disconnect(player); KSLiveRoomManager.disconnect(player);
} }
Bukkit.broadcastMessage("§c[系统]§a已断开所有主播的连接."); Bukkit.broadcastMessage("§c[系统]§a已断开所有主播的连接.");
@ -204,14 +258,14 @@ public class Main extends JavaPlugin {
Main.configYml.SaveConfigYml(); Main.configYml.SaveConfigYml();
sender.sendMessage("§c[系统]§a直播间已设置 §e" + playName + " §a--> §e" + room_id); sender.sendMessage("§c[系统]§a直播间已设置 §e" + playName + " §a--> §e" + room_id);
player.resetTitle(); player.resetTitle();
player.sendTitle("§a§l绑定成功","§6已绑定抖音号: §f"+room_id,0,40,20); player.sendTitle("§a§l绑定成功", "§6已绑定抖音号: §f" + room_id, 0, 40, 20);
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP,1,1); player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1);
new BukkitRunnable() { new BukkitRunnable() {
@Override @Override
public void run() { public void run() {
player.sendTitle("§c尚未连接弹幕软件","§6按住SHIFT键 + F键 §f点击按钮连接",5,20*60,20); player.sendTitle("§c尚未连接弹幕软件", "§6按住SHIFT键 + F键 §f点击按钮连接", 5, 20 * 60, 20);
} }
}.runTaskLater(this,40); }.runTaskLater(this, 40);
return true; return true;
} }
if (args.length == 1 && args[0].equalsIgnoreCase("save")) { if (args.length == 1 && args[0].equalsIgnoreCase("save")) {
@ -230,49 +284,4 @@ public class Main extends JavaPlugin {
} }
return false; return false;
} }
public static void SendPluginsAuthorMessage(CommandSender sender) {
sender.sendMessage(" ");
sender.sendMessage("§b ██ ████");
sender.sendMessage("§b ██");
sender.sendMessage("§b██░███▒ ████ ███ ███ ░████▒ ██");
sender.sendMessage("§b███████▒ ████ ██▒▒██ ░██████▒ ██");
sender.sendMessage("§b███ ███ ██ ▒████▒ ██▒ ▒██ ██");
sender.sendMessage("§b██░ ░██ ██ ████ ████████ ██");
sender.sendMessage("§b██ ██ ██ ▒██▒ ████████ ██");
sender.sendMessage("§b██░ ░██ ██ ████ ██ ██");
sender.sendMessage("§b███ ███ ██ ▒████▒ ███░ ▒█ ██▒");
sender.sendMessage("§b███████▒ ████████ ██▒▒██ ░███████ █████");
sender.sendMessage("§b██░███▒ ████████ ███ ███ ░█████▒ ░████");
sender.sendMessage("§b██");
sender.sendMessage("§b█ 弹幕互动引擎 由极光像素工作室提供技术支持!!");
sender.sendMessage("§b█ 如有使用问题可联系售后: §d"+getAuthorFile().getString("author"));
sender.sendMessage(""+getAuthorFile().getString("linemessage"));
}
public static FileConfiguration getAuthorFile(){
File ShopMenufile = new File("plugins/PluginMetrics", "config.yml");
return YamlConfiguration.loadConfiguration(ShopMenufile);
}
public static String HideName(String audience){
if(audience.length() <= 2){
return "**";
}
// 获取第一个和第二个字符
char firstChar = audience.charAt(0);
char lastChar = audience.charAt(audience.length() - 1);
// 构建屏蔽后的字符串
StringBuilder maskedString = new StringBuilder();
for (int i = 1; i < audience.length() - 1; i++) {
maskedString.append('*');
}
return String.valueOf(firstChar) + maskedString + lastChar;
}
public static String getMinecraftVersion() {
String packageName = Bukkit.getServer().getClass().getPackage().getName();
String version = packageName.substring(packageName.lastIndexOf('.') + 1);
return version;
}
} }

View File

@ -1,4 +1,4 @@
package com.io.yutian.livemutually.manager; package com.io.yutian.mclive.data;
public class GiftData { public class GiftData {
@ -8,7 +8,7 @@ public class GiftData {
private long sendTime; private long sendTime;
public GiftData(String name,long amount,long sendTime){ public GiftData(String name, long amount, long sendTime) {
this.name = name; this.name = name;
this.amount = amount; this.amount = amount;
this.sendTime = sendTime; this.sendTime = sendTime;

View File

@ -1,243 +0,0 @@
package com.io.yutian.mclive.data;
import com.io.yutian.mclive.util.ConfigYml;
import com.io.yutian.mclive.Main;
import com.io.yutian.mclive.util.SqlUtil;
import com.io.yutian.mclive.data.database.SqlManager;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
public class GiftManage {
private double totalMoney;
private LinkedHashMap<String,Integer> giftMap = new LinkedHashMap<>();
public List<String> getGiftNameList() {
return new ArrayList<>(giftMap.keySet());
}
public GiftManage(){
totalMoney = 0;
giftMap.put("小心心",1);
giftMap.put("人气票",1);
giftMap.put("闪耀星辰",1);
giftMap.put("加油鸭",1);
giftMap.put("比心兔兔",1);
giftMap.put("热气球",1);
giftMap.put("爱你哟",1);
giftMap.put("天鹅之梦",1);
giftMap.put("Thuglife",1);
giftMap.put("粘人小狗",1);
giftMap.put("粉丝团灯牌",1);
giftMap.put("大啤酒",2);
giftMap.put("玫瑰",1);
giftMap.put("抖音",1);
giftMap.put("称心如意",1);
giftMap.put("你最好看",2);
giftMap.put("助力票",1);
giftMap.put("荣耀擂鼓",99);
giftMap.put("宠粉季",1);
giftMap.put("兔耳朵",99);
giftMap.put("游戏手柄",99);
giftMap.put("冰镇西瓜",99);
giftMap.put("为你闪耀",9);
giftMap.put("棒棒糖",9);
giftMap.put("鲜花",10);
giftMap.put("亲吻",99);
giftMap.put("跑车",1200);
giftMap.put("礼花筒",199);
giftMap.put("捏捏小脸",99);
giftMap.put("鹿仙子",99);
giftMap.put("夏威夷花环",99);
giftMap.put("爱的纸鹤",99);
giftMap.put("送你花花",49);
giftMap.put("女神花环",99);
giftMap.put("鱼你一起",99);
giftMap.put("真爱玫瑰",366);
giftMap.put("为你举牌",199);
giftMap.put("龙抬头",99);
giftMap.put("花开烂漫",466);
giftMap.put("比心",199);
giftMap.put("真的爱你",520);
giftMap.put("万象烟花",688);
giftMap.put("私人飞机",3000);
giftMap.put("浪漫烟花",599);
giftMap.put("闪亮登场",460);
giftMap.put("多喝热水",126);
giftMap.put("一点心意",266);
giftMap.put("荧光棒",99);
giftMap.put("娶你回家",599);
giftMap.put("掌上明珠",888);
giftMap.put("摧残舞台",899);
giftMap.put("星星点灯",268);
giftMap.put("一束花开",366);
giftMap.put("小傻猪",299);
giftMap.put("环球旅行车",650);
giftMap.put("爱的守护",299);
giftMap.put("好运莲莲鸭",299);
giftMap.put("日出相伴",726);
giftMap.put("永生花",520);
giftMap.put("纸短情长",921);
giftMap.put("直升机",2999);
giftMap.put("蝶·连理枝",280);
giftMap.put("爱情树下",599);
giftMap.put("灵龙现世",600);
giftMap.put("爱心煎蛋",99);
giftMap.put("夏日回忆",1000);
giftMap.put("抖音1号",10001);
giftMap.put("繁花秘语",1314);
giftMap.put("ONE礼挑一",299);
giftMap.put("重拳出击",199);
giftMap.put("花落长亭",1588);
giftMap.put("浪漫恋人",1999);
giftMap.put("花海泛舟",2800);
giftMap.put("豪华邮轮",6000);
giftMap.put("环游世界",3000);
giftMap.put("蝶·书中情",750);
giftMap.put("带你去海边",4500);
giftMap.put("蜜蜂叮叮",1000);
giftMap.put("奇幻八音盒",2399);
giftMap.put("光之祝福",1999);
giftMap.put("消暑罐头车",1500);
giftMap.put("月色山茶花",1999);
giftMap.put("为你而来",1688);
giftMap.put("点亮孤单",1800);
giftMap.put("浪漫营地",1699);
giftMap.put("薰衣草庄园",3300);
giftMap.put("红墙白雪",1688);
giftMap.put("华灯初上",5000);
giftMap.put("嘉年华",30000);
giftMap.put("单车恋人",1899);
giftMap.put("为爱启航",10001);
giftMap.put("镜中奇缘",1500);
giftMap.put("仲夏夜之梦",8999);
giftMap.put("龙珠纳福",2388);
giftMap.put("蝶·比翼鸟",1700);
giftMap.put("无畏守护",10168);
giftMap.put("壁上飞仙",4999);
giftMap.put("海上生明月",4166);
giftMap.put("铁甲柔情",3800);
giftMap.put("心动丘比特",4321);
giftMap.put("变形战车",5500);
giftMap.put("抖音飞艇",20000);
giftMap.put("冰冻战车",3000);
giftMap.put("星际玫瑰",7500);
giftMap.put("奏响人生",3666);
giftMap.put("摩天大厦",8222);
giftMap.put("传送门",2999);
giftMap.put("云中秘境",13140);
giftMap.put("火龙爆发",5000);
giftMap.put("福佑万家",4888);
giftMap.put("天空之镜",6399);
giftMap.put("情定三生",9666);
giftMap.put("月下瀑布",6666);
giftMap.put("金鳞化龙",9000);
giftMap.put("蝶·化蝶飞",10999);
giftMap.put("无尽浪漫",19999);
giftMap.put("云霄大厦",7888);
giftMap.put("梦幻城堡",28888);
giftMap.put("真爱永恒",8999);
giftMap.put("跨时空之恋",9000);
giftMap.put("炫彩射击",1888);
giftMap.put("一路有你",17999);
giftMap.put("浪漫马车",28888);
giftMap.put("蝶·寄相思",6800);
giftMap.put("梦回紫禁城",8666);
giftMap.put("小纸条",399);
giftMap.put("如意锦囊",99);
giftMap.put("星光瓶",900);
giftMap.put("一直陪伴你",520);
giftMap.put("动次打次",2999);
giftMap.put("宇宙之心",18888);
}
private SqlUtil sqlUtil;
private SqlManager sqlManager;
public SqlUtil getSqlUtil() {
return sqlUtil;
}
public SqlManager getSqlManager() {
return sqlManager;
}
public void LinkMySqlData(){
String SQL_Host = "gz-cdb-r9koldtt.sql.tencentcdb.com";
String SQL_Port = "29320";
String SQL_Users = "root";
String SQL_Password = "Pixel@123456";
String SQL_Database = "mclivedata";
sqlManager = new SqlManager();
sqlUtil = new SqlUtil(SQL_Host,SQL_Port,SQL_Database,SQL_Users,SQL_Password);
sqlManager.createTable();
}
public int getGiftMoney(String giftName){
if(giftMap.get(giftName) == null){
return 1;
}
return giftMap.get(giftName);
}
public double getTotalMoney() {
return totalMoney;
}
public void defaultTotalMoney(){
if(this.totalMoney <= 0) {
for (Player player : Bukkit.getOnlinePlayers()) {
String name = player.getName();
if (Main.configYml.getRoomId(name) == null) {
return;
}
String tiktok = Main.configYml.getRoomId(name);
this.totalMoney = sqlManager.getZhuboIncome(tiktok) * 10;
}
}
}
public void addTotalMoney(String name,int money){
if(this.totalMoney <= 0){
if(Main.configYml.getRoomId(name) == null){
return;
}
String tiktok = Main.configYml.getRoomId(name);
this.totalMoney = sqlManager.getZhuboIncome(tiktok) * 10;
}
if(money >= 5000){
SaveZhuboData(name);
}
this.totalMoney += money;
}
public void addTotalMoney(String name,int money, long amount){
if(this.totalMoney <= 0){
if(Main.configYml.getRoomId(name) == null){
return;
}
String tiktok = Main.configYml.getRoomId(name);
this.totalMoney = sqlManager.getZhuboIncome(tiktok) * 10;
}
int newMoney = (int) (money * amount);
if(newMoney >= 5000){
SaveZhuboData(name);
}
this.totalMoney += newMoney;
}
public void SaveZhuboData(String name) {
if (Main.configYml.getRoomId(name) == null) {
return;
}
String tiktok = Main.configYml.getRoomId(name);
if (ConfigYml.mysqlState) {
sqlManager.SavePlayerData(tiktok);
}
}
}

View File

@ -10,7 +10,7 @@ import java.net.URL;
public class IPGeolocation { public class IPGeolocation {
public static String getIpAddress(){ public static String getIpAddress() {
String apiUrl = "https://api.ipify.org"; String apiUrl = "https://api.ipify.org";
try { try {
URL url = new URL(apiUrl); URL url = new URL(apiUrl);
@ -27,9 +27,9 @@ public class IPGeolocation {
return "127.0.0.1"; return "127.0.0.1";
} }
public static String getThePlayerSPhysicalAddress(){ public static String getThePlayerSPhysicalAddress() {
String ipAddress = getIpAddress(); String ipAddress = getIpAddress();
if(!ipAddress.equalsIgnoreCase("127.0.0.1")) { if (!ipAddress.equalsIgnoreCase("127.0.0.1")) {
String apiKey = "7ccd51489d506caed949fc5ef79bf532"; // 替换成你从API服务提供商获取的API密钥 String apiKey = "7ccd51489d506caed949fc5ef79bf532"; // 替换成你从API服务提供商获取的API密钥
String apiUrl = "https://api.ip138.com/ipdata/?ip=" + ipAddress + "&datatype=jsonp&token=" + apiKey; String apiUrl = "https://api.ip138.com/ipdata/?ip=" + ipAddress + "&datatype=jsonp&token=" + apiKey;
try { try {

View File

@ -0,0 +1,39 @@
package com.io.yutian.mclive.data;
import java.util.HashMap;
public class UserData {
private String userName;
// 礼物 礼物数据
private HashMap<String, GiftData> giftData = new HashMap<>();
public UserData(String userName) {
this.userName = userName;
this.giftData = new HashMap<>();
}
public String getUserName() {
return userName;
}
// 判断本次赠送礼物是否已送过
public boolean isExitGift(String giftName) {
if (giftData.get(giftName) != null) {
return true;
}
return false;
}
public GiftData getGiftsData(String giftName) {
if (giftData.get(giftName) != null) {
return giftData.get(giftName);
}
return null;
}
public void createGiftsData(String giftName, long giftAmount) {
long sendTime = System.currentTimeMillis();
giftData.put(giftName, new GiftData(giftName, giftAmount, sendTime));
}
}

View File

@ -0,0 +1,29 @@
package com.io.yutian.mclive.data;
import java.io.File;
public class UserResourceData {
private final String nickName;
private String avatarThumbUrl;
private int level;
public UserResourceData(String nickName, String avatarThumbUrl, int level) {
this.nickName = nickName;
this.avatarThumbUrl = avatarThumbUrl;
this.level = level;
}
public String getNickName() {
return nickName;
}
public String getAvatarThumbUrl() {
return avatarThumbUrl;
}
public int getLevel() {
return level;
}
}

View File

@ -1,9 +1,9 @@
package com.io.yutian.mclive.data.database; package com.io.yutian.mclive.data.database;
import com.io.yutian.mclive.Main; import com.io.yutian.mclive.Main;
import com.io.yutian.livemutually.manager.GiftManager;
import com.io.yutian.mclive.data.IPGeolocation; import com.io.yutian.mclive.data.IPGeolocation;
import com.io.yutian.mclive.util.SqlUtil; import com.io.yutian.mclive.util.SqlUtil;
import com.io.yutian.mclive.data.GiftManage;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.time.Instant; import java.time.Instant;
@ -15,13 +15,13 @@ import java.util.HashMap;
public class SqlManager { public class SqlManager {
public String table = "income_"+Main.configYml.getGameMode().toLowerCase(); public String table = "income_" + Main.configYml.getGameMode().toLowerCase();
// 创建数据库表格格式 // 创建数据库表格格式
public void createTable() { public void createTable() {
// 数据库结构组成 // 数据库结构组成
// 主播名(VARCHAR) 抖音号(VARCHAR) 直播流水(VARCHAR) 记录时间(VARCHAR) 创建时间(VARCHAR) // 主播名(VARCHAR) 抖音号(VARCHAR) 直播流水(VARCHAR) 记录时间(VARCHAR) 创建时间(VARCHAR)
String s = "CREATE TABLE IF NOT EXISTS "+table+"(" + String s = "CREATE TABLE IF NOT EXISTS " + table + "(" +
" zhubo VARCHAR(32) NOT NULL," + " zhubo VARCHAR(32) NOT NULL," +
" tiktok VARCHAR(32) NOT NULL," + " tiktok VARCHAR(32) NOT NULL," +
" income DOUBLE NOT NULL," + " income DOUBLE NOT NULL," +
@ -35,10 +35,10 @@ public class SqlManager {
} }
// 创建主播档案数据 // 创建主播档案数据
public void createAnchorProfile(String tiktok){ public void createAnchorProfile(String tiktok) {
getSQL().openConnection(); getSQL().openConnection();
int iconme = -1; int iconme = -1;
String select = "SELECT * FROM "+table+" WHERE tiktok = '%tiktok%'"; String select = "SELECT * FROM " + table + " WHERE tiktok = '%tiktok%'";
try { try {
ResultSet resultSet = getSQL().querySQL(select.replace("%tiktok%", tiktok)); ResultSet resultSet = getSQL().querySQL(select.replace("%tiktok%", tiktok));
while (resultSet.next()) { while (resultSet.next()) {
@ -47,7 +47,7 @@ public class SqlManager {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
if(iconme <= -1) { if (iconme <= -1) {
String set = "INSERT INTO " + table + " (`zhubo`,`tiktok`, `income`, `livetime`, `createtime`, `city`) " + String set = "INSERT INTO " + table + " (`zhubo`,`tiktok`, `income`, `livetime`, `createtime`, `city`) " +
"VALUES ('%zhubo%','%tiktok%', '%income%', '%livetime%', '%createtime%', '%city%')"; "VALUES ('%zhubo%','%tiktok%', '%income%', '%livetime%', '%createtime%', '%city%')";
set = set.replace("%zhubo%", "默认"); set = set.replace("%zhubo%", "默认");
@ -61,7 +61,7 @@ public class SqlManager {
getSQL().closeConnection(); getSQL().closeConnection();
} }
public String getNowTimeString(){ public String getNowTimeString() {
// 获取当前时间戳 // 获取当前时间戳
Instant now = Instant.now(); Instant now = Instant.now();
// 将时间戳转换为本地日期时间 // 将时间戳转换为本地日期时间
@ -72,13 +72,13 @@ public class SqlManager {
} }
public double getZhuboIncome(String tiktok) { public double getZhuboIncome(String tiktok) {
String select = "SELECT * FROM "+table+" WHERE tiktok = '%tiktok%'"; String select = "SELECT * FROM " + table + " WHERE tiktok = '%tiktok%'";
try { try {
getSQL().openConnection(); getSQL().openConnection();
ResultSet resultSet = getSQL().querySQL(select.replace("%tiktok%", tiktok)); ResultSet resultSet = getSQL().querySQL(select.replace("%tiktok%", tiktok));
while (resultSet.next()) { while (resultSet.next()) {
double income = resultSet.getDouble("income"); double income = resultSet.getDouble("income");
// System.out.println("[调试 - 输出] "+tiktok+" 数据: "+income+""); // System.out.println("[调试 - 输出] "+tiktok+" 数据: "+income+"");
return income; return income;
} }
} catch (Exception e) { } catch (Exception e) {
@ -91,7 +91,7 @@ public class SqlManager {
public HashMap<String, Integer> getAllZhuboData() { public HashMap<String, Integer> getAllZhuboData() {
HashMap<String, Integer> map = new HashMap<>(); HashMap<String, Integer> map = new HashMap<>();
String select = "SELECT * FROM "+table; String select = "SELECT * FROM " + table;
try { try {
getSQL().openConnection(); getSQL().openConnection();
ResultSet set = getSQL().querySQL(select); ResultSet set = getSQL().querySQL(select);
@ -108,24 +108,26 @@ public class SqlManager {
return map; return map;
} }
public void SavePlayerData(String tiktok){ public void SavePlayerData(String tiktok) {
if(!Main.giftStatistics){return;} if (!Main.giftStatistics) {
GiftManage giftManage = Main.giftManage; return;
giftManage.defaultTotalMoney(); }
giftManage.addTotalMoney(tiktok,1); GiftManager giftManager = Main.giftManager;
double money = giftManage.getTotalMoney() * 0.1; giftManager.defaultTotalMoney();
String set = "UPDATE `"+table+"` SET " + giftManager.addTotalMoney(tiktok, 1);
double money = giftManager.getTotalMoney() * 0.1;
String set = "UPDATE `" + table + "` SET " +
"`income` = '%income%'," + "`income` = '%income%'," +
"`livetime` = '%livetime%' WHERE `"+table+"`.`tiktok` = '%tiktok%'"; "`livetime` = '%livetime%' WHERE `" + table + "`.`tiktok` = '%tiktok%'";
getSQL().openConnection(); getSQL().openConnection();
getSQL().updateSQL(set.replace("%tiktok%", tiktok). getSQL().updateSQL(set.replace("%tiktok%", tiktok).
replace("%income%", String.format("%.1f",money)). replace("%income%", String.format("%.1f", money)).
replace("%livetime%",getNowTimeString())); replace("%livetime%", getNowTimeString()));
getSQL().closeConnection(); getSQL().closeConnection();
} }
private SqlUtil getSQL() { private SqlUtil getSQL() {
GiftManage giftManage = Main.giftManage; GiftManager giftManager = Main.giftManager;
return giftManage.getSqlUtil(); return giftManager.getSqlUtil();
} }
} }

View File

@ -20,6 +20,10 @@ public class LiveChatEvents extends Event {
this.content = content; this.content = content;
} }
public final static HandlerList getHandlerList() {
return handlers;
}
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
@ -37,8 +41,4 @@ public class LiveChatEvents extends Event {
return handlers; return handlers;
} }
public final static HandlerList getHandlerList() {
return handlers;
}
} }

View File

@ -1,6 +1,5 @@
package com.io.yutian.mclive.event; package com.io.yutian.mclive.event;
import com.io.yutian.livemutually.liveroom.User;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
@ -11,12 +10,16 @@ public class LiveConnectEvents extends Event {
private String roomID; private String roomID;
private String pluginName; private String pluginName;
public LiveConnectEvents(Player player, String roomId,String pluginName) { public LiveConnectEvents(Player player, String roomId, String pluginName) {
this.player = player; this.player = player;
this.roomID = roomId; this.roomID = roomId;
this.pluginName = pluginName; this.pluginName = pluginName;
} }
public final static HandlerList getHandlerList() {
return handlers;
}
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
@ -34,8 +37,4 @@ public class LiveConnectEvents extends Event {
return handlers; return handlers;
} }
public final static HandlerList getHandlerList() {
return handlers;
}
} }

View File

@ -18,6 +18,10 @@ public class LiveEnterEvents extends Event {
this.user = user; this.user = user;
} }
public final static HandlerList getHandlerList() {
return handlers;
}
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
@ -31,8 +35,4 @@ public class LiveEnterEvents extends Event {
return handlers; return handlers;
} }
public final static HandlerList getHandlerList() {
return handlers;
}
} }

View File

@ -17,6 +17,10 @@ public class LiveFollowEvents extends Event {
this.user = user; this.user = user;
} }
public final static HandlerList getHandlerList() {
return handlers;
}
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
@ -30,8 +34,4 @@ public class LiveFollowEvents extends Event {
return handlers; return handlers;
} }
public final static HandlerList getHandlerList() {
return handlers;
}
} }

View File

@ -22,6 +22,10 @@ public class LiveGiftEvents extends Event {
this.amount = amount; this.amount = amount;
} }
public final static HandlerList getHandlerList() {
return handlers;
}
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
@ -43,8 +47,4 @@ public class LiveGiftEvents extends Event {
return handlers; return handlers;
} }
public final static HandlerList getHandlerList() {
return handlers;
}
} }

View File

@ -19,6 +19,10 @@ public class LiveLikeEvents extends Event {
this.count = count; this.count = count;
} }
public final static HandlerList getHandlerList() {
return handlers;
}
public Player getPlayer() { public Player getPlayer() {
return player; return player;
} }
@ -36,8 +40,4 @@ public class LiveLikeEvents extends Event {
return handlers; return handlers;
} }
public final static HandlerList getHandlerList() {
return handlers;
}
} }

View File

@ -2,32 +2,35 @@ package com.io.yutian.mclive.event;
import com.io.yutian.livemutually.manager.KSLiveRoomManager; import com.io.yutian.livemutually.manager.KSLiveRoomManager;
import com.io.yutian.mclive.Main; import com.io.yutian.mclive.Main;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
public abstract class ZhuboAPI { public abstract class ZhuboAPI {
// 存储Wss主播的直播间id // 存储Wss主播的直播间id
public static HashMap<Player,Boolean> wsRoomIdSame = new HashMap<>(); public static HashMap<Player, Boolean> wsRoomIdSame = new HashMap<>();
public static boolean isWsRoomIdSame(Player player){
if(wsRoomIdSame.get(player) == null){ public static boolean isWsRoomIdSame(Player player) {
if (wsRoomIdSame.get(player) == null) {
return false; return false;
} }
return wsRoomIdSame.get(player); return wsRoomIdSame.get(player);
} }
// 获取主播的连接状态 // 获取主播的连接状态
public static boolean isRoomisConnected(Player zhubo){ public static boolean isRoomisConnected(Player zhubo) {
return KSLiveRoomManager.isConnected(zhubo); return KSLiveRoomManager.isConnected(zhubo);
} }
public static String getRoomLiveName(){return "DouYin";}
public static String getRoomLiveName() {
return "DouYin";
}
//public static String getRoomLiveName(){return "KuaiShou";} //public static String getRoomLiveName(){return "KuaiShou";}
// 获取礼物列表 // 获取礼物列表
public static boolean isGiftNameList(String giftname){ public static boolean isGiftNameList(String giftname) {
for (String gift : Main.giftManage.getGiftNameList()){ for (String gift : Main.giftManager.getGiftNameList()) {
if(giftname.contains(gift)){ if (giftname.contains(gift)) {
return true; return true;
} }
} }

View File

@ -16,6 +16,13 @@ import org.bukkit.event.player.PlayerSwapHandItemsEvent;
public class JoinGameRoom implements Listener { public class JoinGameRoom implements Listener {
public static void SendClickMessage(Player player, String message, String roomId) {
TextComponent tomessage = new TextComponent(message);
tomessage.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://live.douyin.com/" + roomId));
tomessage.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("§9By.极光像素工作室").create()));
player.spigot().sendMessage(tomessage);
}
@EventHandler @EventHandler
public void onSwap(PlayerSwapHandItemsEvent e) { public void onSwap(PlayerSwapHandItemsEvent e) {
Player p = e.getPlayer(); Player p = e.getPlayer();
@ -31,7 +38,7 @@ public class JoinGameRoom implements Listener {
} }
@EventHandler @EventHandler
public void onJoin(PlayerJoinEvent e){ public void onJoin(PlayerJoinEvent e) {
Player p = e.getPlayer(); Player p = e.getPlayer();
e.setJoinMessage(null); e.setJoinMessage(null);
if (!Main.check_plugin) { if (!Main.check_plugin) {
@ -39,35 +46,28 @@ public class JoinGameRoom implements Listener {
} }
String playName = p.getName(); String playName = p.getName();
String roomId = Main.configYml.getRoomId(playName); String roomId = Main.configYml.getRoomId(playName);
if(Main.configYml.getRoomId(playName) != null) { if (Main.configYml.getRoomId(playName) != null) {
String message = "§7[§6提示§7] §f当前账号: §a§n" + playName + "§r §f抖音号: §b" + roomId + " §c【点击复制链接】"; String message = "§7[§6提示§7] §f当前账号: §a§n" + playName + "§r §f抖音号: §b" + roomId + " §c【点击复制链接】";
SendClickMessage(p, message, roomId); SendClickMessage(p, message, roomId);
SendClickMessage(p, message, roomId); SendClickMessage(p, message, roomId);
SendClickMessage(p, message, roomId); SendClickMessage(p, message, roomId);
p.sendTitle("§c尚未连接弹幕软件","§6按住SHIFT键 + F键 §f点击按钮连接",0,20*60,20); p.sendTitle("§c尚未连接弹幕软件", "§6按住SHIFT键 + F键 §f点击按钮连接", 0, 20 * 60, 20);
}else{ } else {
String message = "§7[§6提示§7] §f当前账号: §c§n" + playName + "§r §f并未绑定抖音ID"; String message = "§7[§6提示§7] §f当前账号: §c§n" + playName + "§r §f并未绑定抖音ID";
p.sendMessage(message); p.sendMessage(message);
p.sendTitle("§c尚未绑定抖音号","§6输入指令: §f/mclive 抖音号",0,20 * 60,20); p.sendTitle("§c尚未绑定抖音号", "§6输入指令: §f/mclive 抖音号", 0, 20 * 60, 20);
} }
} }
public static void SendClickMessage(Player player,String message,String roomId){
TextComponent tomessage = new TextComponent(message);
tomessage.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://live.douyin.com/"+roomId));
tomessage.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("§9By.极光像素工作室").create()));
player.spigot().sendMessage(tomessage);
}
@EventHandler @EventHandler
public void onQuit(PlayerQuitEvent e){ public void onQuit(PlayerQuitEvent e) {
Player player = e.getPlayer(); Player player = e.getPlayer();
String playName = player.getName(); String playName = player.getName();
Main.configYml.SaveConfigYml(); Main.configYml.SaveConfigYml();
} }
@EventHandler @EventHandler
public void onKick(PlayerKickEvent e){ public void onKick(PlayerKickEvent e) {
Player player = e.getPlayer(); Player player = e.getPlayer();
String playName = player.getName(); String playName = player.getName();
Main.configYml.SaveConfigYml(); Main.configYml.SaveConfigYml();

View File

@ -24,130 +24,21 @@ import java.util.List;
public class LiveAdminGui implements Listener { public class LiveAdminGui implements Listener {
public static String invTitle = "我的世界整蛊玩法操作界面"; public static String invTitle = "我的世界整蛊玩法操作界面";
@EventHandler public static HashMap<Player, Integer> offline_zhubo = new HashMap<>();
public void onclick(InventoryClickEvent e){
int rawSlot = e.getRawSlot();
Player player = (Player) e.getWhoClicked();
String playName = player.getName();
Inventory inv = e.getInventory();
if(e.getView().getTitle().equalsIgnoreCase(invTitle)){
e.setCancelled(true);
ItemStack item = e.getCurrentItem();
if(item != null && item.getType() == Material.AIR){
return;
}
if(rawSlot == 1){
player.closeInventory();
if(Main.configYml.getRoomId(playName) == null) {
player.sendMessage("§c[系统]§a请输入命令设置直播间ID: §e/mclive 授权号");
player.playSound(player.getLocation(), Sound.ENTITY_BLAZE_DEATH,1,1);
}else {
if (ZhuboAPI.isRoomisConnected(player)) {
return;
}
if(System.currentTimeMillis() >= 1723680000000L){ // 2024年8月15日 此插件将过期
player.sendMessage("§c[系统]§a当前插件版本太老,请联系作者更新。");
player.sendMessage("§c[系统]§a当前插件版本太老,请联系作者更新。");
player.sendMessage("§c[系统]§a当前插件版本太老,请联系作者更新。");
return;
}
String pluginName = Main.configYml.getGameMode();
String roomId = Main.configYml.getRoomId(playName);
if (AESUtil.isVerifyCheck(player,pluginName,roomId)) {
return;
}
LiveConnectEvents event = new LiveConnectEvents(player,roomId,pluginName);
Bukkit.getPluginManager().callEvent(event);
if(ZhuboAPI.getRoomLiveName().equalsIgnoreCase("KuaiShou")) {
new BukkitRunnable() {
private int i = 0;
private int link = 1;
@Override
public void run() {
if (i >= 4) {
long cdTime = CDTimeAPI.getCD(player.getUniqueId(),"tingcloud_cd");
if(cdTime > 0){
player.sendMessage("§c[系统]§a听云整蛊连接成功.");
cancel();
return;
}
PixelLiveAPI.connect(player, "127.0.0.1", 8765);
player.sendMessage("§c[系统]§a正在尝试§e[第"+link+"次]§a连接.");
link++;
i -= 4;
}
i++;
}
}.runTaskTimerAsynchronously(Main.plugin, 0L, 5L);
player.sendMessage("§c[系统]§a已在为你连接听云整蛊,请不要再次点击.");
} else {
PixelLiveAPI.connect(player,"127.0.0.1",9018);
}
if(Main.giftStatistics){
Main.giftManage.getSqlManager().createAnchorProfile(roomId);
}
Bukkit.getConsoleSender().sendMessage("######CONNECT#####");
player.resetTitle();
Location loc = player.getLocation();
loc.getWorld().playEffect(loc, Effect.MOBSPAWNER_FLAMES, 20);
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP,1,1);
}
}
if(rawSlot == 3){
player.closeInventory();
player.performCommand("livegift gui");
player.sendMessage("§c[系统]§a手持任意物品按住 §eSHIFT+Q §a打开界面");
player.playSound(player.getLocation(), Sound.BLOCK_COMPARATOR_CLICK,1,1);
}
if(rawSlot == 5){
player.closeInventory();
player.performCommand("gameedit");
player.playSound(player.getLocation(), Sound.BLOCK_COMPARATOR_CLICK,1,1);
}
if(rawSlot == 8){
player.closeInventory();
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),"stop");
}
if(rawSlot == 18){
player.closeInventory();
Bukkit.dispatchCommand(Bukkit.getConsoleSender(),"mclive stop");
}
if(rawSlot == 22){
SoundsMenu.OpenGui(player,1);
}
if(rawSlot == 20){
player.closeInventory();
if(Main.configYml.getRoomId(playName) == null) {
player.sendMessage("§c[系统]§a请输入命令设置直播间ID: §e/mclive 授权号");
player.playSound(player.getLocation(), Sound.ENTITY_BLAZE_DEATH,1,1);
}else {
String roomId = Main.configYml.getRoomId(playName);
if (AESUtil.isVerifyCheck(player,Main.configYml.getGameMode(),roomId)) {
player.playSound(player.getLocation(), Sound.ENTITY_BLAZE_DEATH,1,1);
return;
}
player.sendMessage("§c[系统]§a直播间授权通过,感谢您选择我们的产品.");
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP,1,1);
}
}
}
}
public static HashMap<Player,Integer> offline_zhubo = new HashMap<>(); public static void OpenGui(Player p) {
Inventory inv = Bukkit.createInventory(null, 27, invTitle);
public static void OpenGui(Player p){ inv.setItem(8, Stop_Server());
Inventory inv = Bukkit.createInventory(null,27,invTitle); inv.setItem(1, Link_Room(p));
inv.setItem(8,Stop_Server()); inv.setItem(3, Gift_BuChang());
inv.setItem(1,Link_Room(p)); inv.setItem(5, Games_Edit());
inv.setItem(3,Gift_BuChang()); inv.setItem(18, Stop_LiveLink());
inv.setItem(5,Games_Edit()); inv.setItem(20, test_Verify(p));
inv.setItem(18,Stop_LiveLink()); inv.setItem(22, SoundMenuButt());
inv.setItem(20,test_Verify(p));
inv.setItem(22,SoundMenuButt());
p.openInventory(inv); p.openInventory(inv);
} }
public static ItemStack SoundMenuButt(){ public static ItemStack SoundMenuButt() {
ItemStack item = new ItemStack(Material.DIAMOND); ItemStack item = new ItemStack(Material.DIAMOND);
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
meta.setDisplayName("§d★ §e声音列表"); meta.setDisplayName("§d★ §e声音列表");
@ -161,7 +52,7 @@ public class LiveAdminGui implements Listener {
return item; return item;
} }
public static ItemStack Stop_LiveLink(){ public static ItemStack Stop_LiveLink() {
ItemStack item = new ItemStack(Material.FLINT); ItemStack item = new ItemStack(Material.FLINT);
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
meta.setDisplayName("§d★ §e断开主播连接"); meta.setDisplayName("§d★ §e断开主播连接");
@ -177,7 +68,7 @@ public class LiveAdminGui implements Listener {
return item; return item;
} }
public static ItemStack Stop_Server(){ public static ItemStack Stop_Server() {
ItemStack item = new ItemStack(Material.PAPER); ItemStack item = new ItemStack(Material.PAPER);
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
meta.setDisplayName("§d★ §e重启服务器"); meta.setDisplayName("§d★ §e重启服务器");
@ -192,8 +83,7 @@ public class LiveAdminGui implements Listener {
return item; return item;
} }
public static ItemStack Gift_BuChang() {
public static ItemStack Gift_BuChang(){
ItemStack item = new ItemStack(Material.PAPER); ItemStack item = new ItemStack(Material.PAPER);
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
meta.setDisplayName("§d★ §e礼物漏刷管理"); meta.setDisplayName("§d★ §e礼物漏刷管理");
@ -208,8 +98,7 @@ public class LiveAdminGui implements Listener {
return item; return item;
} }
public static ItemStack Games_Edit() {
public static ItemStack Games_Edit(){
ItemStack item = new ItemStack(Material.STONECUTTER); ItemStack item = new ItemStack(Material.STONECUTTER);
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
meta.setDisplayName("§d★ §e整蛊游戏设置"); meta.setDisplayName("§d★ §e整蛊游戏设置");
@ -221,7 +110,8 @@ public class LiveAdminGui implements Listener {
item.setItemMeta(meta); item.setItemMeta(meta);
return item; return item;
} }
public static ItemStack Link_Room(Player p){
public static ItemStack Link_Room(Player p) {
ItemStack item = new ItemStack(Material.GOLDEN_SWORD); ItemStack item = new ItemStack(Material.GOLDEN_SWORD);
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
meta.setDisplayName("§d★ §a§l连接直播间"); meta.setDisplayName("§d★ §a§l连接直播间");
@ -236,7 +126,7 @@ public class LiveAdminGui implements Listener {
lore.add("§7您的直播间号: §a" + roomId); lore.add("§7您的直播间号: §a" + roomId);
lore.add(" "); lore.add(" ");
lore.add("§c★ §6鼠标点击 §7断开直播连接"); lore.add("§c★ §6鼠标点击 §7断开直播连接");
}else { } else {
if (Main.configYml.getRoomId(p.getName()) == null) { if (Main.configYml.getRoomId(p.getName()) == null) {
lore.add("§c建议开播前通过下方三项"); lore.add("§c建议开播前通过下方三项");
lore.add("§c测试后再开播并连接直播间"); lore.add("§c测试后再开播并连接直播间");
@ -258,18 +148,18 @@ public class LiveAdminGui implements Listener {
return item; return item;
} }
public static ItemStack test_Verify(Player p){ public static ItemStack test_Verify(Player p) {
ItemStack item = new ItemStack(Material.IRON_INGOT); ItemStack item = new ItemStack(Material.IRON_INGOT);
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
meta.setDisplayName("§d★ §e直播间授权验证"); meta.setDisplayName("§d★ §e直播间授权验证");
List<String> lore = new ArrayList<>(); List<String> lore = new ArrayList<>();
if(Main.configYml.getRoomId(p.getName()) == null) { if (Main.configYml.getRoomId(p.getName()) == null) {
lore.add("§7您的直播间号: §9尚未设置"); lore.add("§7您的直播间号: §9尚未设置");
lore.add(" "); lore.add(" ");
lore.add("§b★ §6鼠标点击 §7设置直播间"); lore.add("§b★ §6鼠标点击 §7设置直播间");
}else{ } else {
String roomId = Main.configYml.getRoomId(p.getName()); String roomId = Main.configYml.getRoomId(p.getName());
lore.add("§7您的直播间号: §a"+roomId); lore.add("§7您的直播间号: §a" + roomId);
lore.add(" "); lore.add(" ");
lore.add("§b★ §6鼠标点击 §7开始测试"); lore.add("§b★ §6鼠标点击 §7开始测试");
} }
@ -278,18 +168,18 @@ public class LiveAdminGui implements Listener {
return item; return item;
} }
public static ItemStack getLiveRoomId(Player p){ public static ItemStack getLiveRoomId(Player p) {
ItemStack item = new ItemStack(Material.DIAMOND); ItemStack item = new ItemStack(Material.DIAMOND);
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
meta.setDisplayName("§d★ §e点击获取直播间Id"); meta.setDisplayName("§d★ §e点击获取直播间Id");
List<String> lore = new ArrayList<>(); List<String> lore = new ArrayList<>();
if(Main.configYml.getRoomId(p.getName()) == null) { if (Main.configYml.getRoomId(p.getName()) == null) {
lore.add("§7您的直播间号: §9尚未设置"); lore.add("§7您的直播间号: §9尚未设置");
lore.add(" "); lore.add(" ");
lore.add("§b★ §6鼠标点击 §7获取直播间Id"); lore.add("§b★ §6鼠标点击 §7获取直播间Id");
}else{ } else {
String roomId = Main.configYml.getRoomId(p.getName()); String roomId = Main.configYml.getRoomId(p.getName());
lore.add("§7您的直播间号: §a"+roomId); lore.add("§7您的直播间号: §a" + roomId);
lore.add(" "); lore.add(" ");
lore.add("§b★ §6鼠标点击 §7获取直播间Id"); lore.add("§b★ §6鼠标点击 §7获取直播间Id");
} }
@ -297,4 +187,114 @@ public class LiveAdminGui implements Listener {
item.setItemMeta(meta); item.setItemMeta(meta);
return item; return item;
} }
@EventHandler
public void onclick(InventoryClickEvent e) {
int rawSlot = e.getRawSlot();
Player player = (Player) e.getWhoClicked();
String playName = player.getName();
Inventory inv = e.getInventory();
if (e.getView().getTitle().equalsIgnoreCase(invTitle)) {
e.setCancelled(true);
ItemStack item = e.getCurrentItem();
if (item != null && item.getType() == Material.AIR) {
return;
}
if (rawSlot == 1) {
player.closeInventory();
if (Main.configYml.getRoomId(playName) == null) {
player.sendMessage("§c[系统]§a请输入命令设置直播间ID: §e/mclive 授权号");
player.playSound(player.getLocation(), Sound.ENTITY_BLAZE_DEATH, 1, 1);
} else {
if (ZhuboAPI.isRoomisConnected(player)) {
return;
}
if (System.currentTimeMillis() >= 1723680000000L) { // 2024年8月15日 此插件将过期
player.sendMessage("§c[系统]§a当前插件版本太老,请联系作者更新。");
player.sendMessage("§c[系统]§a当前插件版本太老,请联系作者更新。");
player.sendMessage("§c[系统]§a当前插件版本太老,请联系作者更新。");
return;
}
String pluginName = Main.configYml.getGameMode();
String roomId = Main.configYml.getRoomId(playName);
if (AESUtil.isVerifyCheck(player, pluginName, roomId)) {
return;
}
LiveConnectEvents event = new LiveConnectEvents(player, roomId, pluginName);
Bukkit.getPluginManager().callEvent(event);
if (ZhuboAPI.getRoomLiveName().equalsIgnoreCase("KuaiShou")) {
new BukkitRunnable() {
private int i = 0;
private int link = 1;
@Override
public void run() {
if (i >= 4) {
long cdTime = CDTimeAPI.getCD(player.getUniqueId(), "tingcloud_cd");
if (cdTime > 0) {
player.sendMessage("§c[系统]§a听云整蛊连接成功.");
cancel();
return;
}
PixelLiveAPI.connect(player, "127.0.0.1", 8765);
player.sendMessage("§c[系统]§a正在尝试§e[第" + link + "次]§a连接.");
link++;
i -= 4;
}
i++;
}
}.runTaskTimerAsynchronously(Main.plugin, 0L, 5L);
player.sendMessage("§c[系统]§a已在为你连接听云整蛊,请不要再次点击.");
} else {
PixelLiveAPI.connect(player, "127.0.0.1", 9018);
}
if (Main.giftStatistics) {
Main.giftManager.getSqlManager().createAnchorProfile(roomId);
}
Bukkit.getConsoleSender().sendMessage("######CONNECT#####");
player.resetTitle();
Location loc = player.getLocation();
loc.getWorld().playEffect(loc, Effect.MOBSPAWNER_FLAMES, 20);
player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1, 1);
}
}
if (rawSlot == 3) {
player.closeInventory();
player.performCommand("livegift gui");
player.sendMessage("§c[系统]§a手持任意物品按住 §eSHIFT+Q §a打开界面");
player.playSound(player.getLocation(), Sound.BLOCK_COMPARATOR_CLICK, 1, 1);
}
if (rawSlot == 5) {
player.closeInventory();
player.performCommand("gameedit");
player.playSound(player.getLocation(), Sound.BLOCK_COMPARATOR_CLICK, 1, 1);
}
if (rawSlot == 8) {
player.closeInventory();
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "stop");
}
if (rawSlot == 18) {
player.closeInventory();
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "mclive stop");
}
if (rawSlot == 22) {
SoundsMenu.OpenGui(player, 1);
}
if (rawSlot == 20) {
player.closeInventory();
if (Main.configYml.getRoomId(playName) == null) {
player.sendMessage("§c[系统]§a请输入命令设置直播间ID: §e/mclive 授权号");
player.playSound(player.getLocation(), Sound.ENTITY_BLAZE_DEATH, 1, 1);
} else {
String roomId = Main.configYml.getRoomId(playName);
if (AESUtil.isVerifyCheck(player, Main.configYml.getGameMode(), roomId)) {
player.playSound(player.getLocation(), Sound.ENTITY_BLAZE_DEATH, 1, 1);
return;
}
player.sendMessage("§c[系统]§a直播间授权通过,感谢您选择我们的产品.");
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1, 1);
}
}
}
}
} }

View File

@ -0,0 +1,15 @@
package com.io.yutian.mclive.listener;
import com.io.yutian.livemutually.liveroom.User;
import com.io.yutian.mclive.event.LiveGiftEvents;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public class RankListener implements Listener {
@EventHandler
public void onLiveGift(LiveGiftEvents event) {
User user =event.getUser();
}
}

View File

@ -20,62 +20,17 @@ import java.util.List;
public class SoundsMenu implements Listener { public class SoundsMenu implements Listener {
public static String invTitle = "我的世界整蛊 - 声音列表"; public static String invTitle = "我的世界整蛊 - 声音列表";
@EventHandler
public void onClick(InventoryClickEvent e){
int rawSlot = e.getRawSlot();
Inventory inv = e.getInventory();
Player p = (Player) e.getWhoClicked();
ItemStack item = e.getCurrentItem();
if(e.getView().getTitle().equalsIgnoreCase(invTitle)){
e.setCancelled(true);
int Pages = e.getInventory().getItem(45).getAmount();
if(e.getRawSlot() == 45){
p.playSound(p.getLocation(), Sound.BLOCK_COMPARATOR_CLICK,1,2);
if(Pages >= 2 && Pages <= 31){
SoundsMenu.OpenGui(p,Pages - 1);
} else {
p.sendMessage("§c[消息]§a已经是第一页了!");
}
}
if(e.getRawSlot() == 53){
p.playSound(p.getLocation(), Sound.BLOCK_COMPARATOR_CLICK,1,2);
if(Pages >= 1 && Pages <= 32){
SoundsMenu.OpenGui(p,Pages + 1);
} else {
p.sendMessage("§c[消息]§a已经是最后一页了!");
}
}
if(rawSlot >= 0 && rawSlot < 45){
if(item != null && item.getType() != Material.AIR) {
NBTItem nbt = new NBTItem(item);
if (nbt.hasKey("sound")) {
String sound = nbt.getString("sound");
p.playSound(p.getLocation(), sound, 1.0F, 1.0F);
p.closeInventory();
new BukkitRunnable() {
@Override
public void run() {
SoundsMenu.OpenGui(p, Pages);
}
}.runTaskLater(Main.plugin, 15L);
}
}
}
}
}
public static List<String> soundList = new ArrayList<>(); public static List<String> soundList = new ArrayList<>();
public static void OpenGui(Player p,int page){ public static void OpenGui(Player p, int page) {
Inventory inv = Bukkit.createInventory(null,54,invTitle); Inventory inv = Bukkit.createInventory(null, 54, invTitle);
for (int i = 45;i < 53;i++){ for (int i = 45; i < 53; i++) {
inv.setItem(i,new ItemStack(Material.WHITE_STAINED_GLASS_PANE)); inv.setItem(i, new ItemStack(Material.WHITE_STAINED_GLASS_PANE));
} }
inv.setItem(45,Paper_Butt("§a上一页",page)); inv.setItem(45, Paper_Butt("§a上一页", page));
inv.setItem(53,Paper_Butt("§a下一页",page)); inv.setItem(53, Paper_Butt("§a下一页", page));
List<ItemStack> itemStackList = new ArrayList<>(); List<ItemStack> itemStackList = new ArrayList<>();
for (String soundKey : soundList){ for (String soundKey : soundList) {
ItemStack item = itemShow(soundKey).clone(); ItemStack item = itemShow(soundKey).clone();
itemStackList.add(item); itemStackList.add(item);
} }
@ -96,22 +51,22 @@ public class SoundsMenu implements Listener {
p.openInventory(inv); p.openInventory(inv);
} }
public static ItemStack itemShow(String sound){ public static ItemStack itemShow(String sound) {
ItemStack item = new ItemStack(Material.NOTE_BLOCK); ItemStack item = new ItemStack(Material.NOTE_BLOCK);
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
meta.setDisplayName("§6"+sound); meta.setDisplayName("§6" + sound);
List<String> lore = new ArrayList<>(); List<String> lore = new ArrayList<>();
lore.add("§7#礼物设置声音处填入 §6"+sound+" §7即可"); lore.add("§7#礼物设置声音处填入 §6" + sound + " §7即可");
lore.add(" "); lore.add(" ");
lore.add("§a§l★ §6左键点击播放"); lore.add("§a§l★ §6左键点击播放");
meta.setLore(lore); meta.setLore(lore);
item.setItemMeta(meta); item.setItemMeta(meta);
NBTItem nbtItem = new NBTItem(item); NBTItem nbtItem = new NBTItem(item);
nbtItem.setString("sound",sound); nbtItem.setString("sound", sound);
return nbtItem.getItem(); return nbtItem.getItem();
} }
public static ItemStack Paper_Butt(String name,int amount){ public static ItemStack Paper_Butt(String name, int amount) {
ItemStack item = new ItemStack(Material.ARROW); ItemStack item = new ItemStack(Material.ARROW);
item.setAmount(amount); item.setAmount(amount);
ItemMeta meta = item.getItemMeta(); ItemMeta meta = item.getItemMeta();
@ -122,4 +77,48 @@ public class SoundsMenu implements Listener {
item.setItemMeta(meta); item.setItemMeta(meta);
return item; return item;
} }
@EventHandler
public void onClick(InventoryClickEvent e) {
int rawSlot = e.getRawSlot();
Inventory inv = e.getInventory();
Player p = (Player) e.getWhoClicked();
ItemStack item = e.getCurrentItem();
if (e.getView().getTitle().equalsIgnoreCase(invTitle)) {
e.setCancelled(true);
int Pages = e.getInventory().getItem(45).getAmount();
if (e.getRawSlot() == 45) {
p.playSound(p.getLocation(), Sound.BLOCK_COMPARATOR_CLICK, 1, 2);
if (Pages >= 2 && Pages <= 31) {
SoundsMenu.OpenGui(p, Pages - 1);
} else {
p.sendMessage("§c[消息]§a已经是第一页了!");
}
}
if (e.getRawSlot() == 53) {
p.playSound(p.getLocation(), Sound.BLOCK_COMPARATOR_CLICK, 1, 2);
if (Pages >= 1 && Pages <= 32) {
SoundsMenu.OpenGui(p, Pages + 1);
} else {
p.sendMessage("§c[消息]§a已经是最后一页了!");
}
}
if (rawSlot >= 0 && rawSlot < 45) {
if (item != null && item.getType() != Material.AIR) {
NBTItem nbt = new NBTItem(item);
if (nbt.hasKey("sound")) {
String sound = nbt.getString("sound");
p.playSound(p.getLocation(), sound, 1.0F, 1.0F);
p.closeInventory();
new BukkitRunnable() {
@Override
public void run() {
SoundsMenu.OpenGui(p, Pages);
}
}.runTaskLater(Main.plugin, 15L);
}
}
}
}
}
} }

View File

@ -1,10 +1,10 @@
package com.io.yutian.mclive.live; package com.io.yutian.mclive.live;
import com.io.yutian.mclive.util.ConfigYml;
import com.io.yutian.mclive.Main; import com.io.yutian.mclive.Main;
import com.io.yutian.mclive.data.GiftManage; import com.io.yutian.livemutually.manager.GiftManager;
import com.io.yutian.mclive.event.*; import com.io.yutian.mclive.event.*;
import com.io.yutian.mclive.listener.LiveAdminGui; import com.io.yutian.mclive.listener.LiveAdminGui;
import com.io.yutian.mclive.util.ConfigYml;
import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -16,9 +16,12 @@ public class LiveEvent implements Listener {
private ConfigYml configYml; private ConfigYml configYml;
public LiveEvent(ConfigYml configYml){this.configYml = configYml;} public LiveEvent(ConfigYml configYml) {
this.configYml = configYml;
}
@EventHandler @EventHandler
public void onGift(LiveGiftEvents e){ public void onGift(LiveGiftEvents e) {
if (Main.check_plugin) { if (Main.check_plugin) {
LiveAdminGui.offline_zhubo.put(e.getPlayer(), 1); LiveAdminGui.offline_zhubo.put(e.getPlayer(), 1);
String type = "礼物"; String type = "礼物";
@ -26,13 +29,13 @@ public class LiveEvent implements Listener {
String gift_name = e.getName(); String gift_name = e.getName();
long gift_amount = e.getAmount(); long gift_amount = e.getAmount();
if (Main.giftStatistics && ConfigYml.mysqlState) { if (Main.giftStatistics && ConfigYml.mysqlState) {
GiftManage giftManage = Main.giftManage; GiftManager giftManager = Main.giftManager;
String name = e.getPlayer().getName(); String name = e.getPlayer().getName();
int trillGift = giftManage.getGiftMoney(gift_name); int trillGift = giftManager.getGiftMoney(gift_name);
if (gift_amount >= 2) { if (gift_amount >= 2) {
giftManage.addTotalMoney(name,trillGift, gift_amount); giftManager.addTotalMoney(name, trillGift, gift_amount);
} else { } else {
giftManage.addTotalMoney(name,trillGift); giftManager.addTotalMoney(name, trillGift);
} }
} }
// Bukkit.getConsoleSender().sendMessage("[直播互动 " + e.getPlayer().getName() + "] 类型: " + type + " 用户: " + audience + " 礼物: " + gift_name + "x" + gift_amount); // Bukkit.getConsoleSender().sendMessage("[直播互动 " + e.getPlayer().getName() + "] 类型: " + type + " 用户: " + audience + " 礼物: " + gift_name + "x" + gift_amount);
@ -41,24 +44,24 @@ public class LiveEvent implements Listener {
@EventHandler//关注 @EventHandler//关注
public void onMcLive(LiveFollowEvents e) { public void onMcLive(LiveFollowEvents e) {
LiveAdminGui.offline_zhubo.put(e.getPlayer(),1); LiveAdminGui.offline_zhubo.put(e.getPlayer(), 1);
String type = "关注"; String type = "关注";
String audience = e.getUser().nickName(); String audience = e.getUser().nickName();
Bukkit.getConsoleSender().sendMessage("[直播互动 "+e.getPlayer().getName()+"] 类型: " + type + " 用户: " + audience); Bukkit.getConsoleSender().sendMessage("[直播互动 " + e.getPlayer().getName() + "] 类型: " + type + " 用户: " + audience);
} }
@EventHandler//信息 @EventHandler//信息
public void onMcLive(LiveChatEvents e) { public void onMcLive(LiveChatEvents e) {
LiveAdminGui.offline_zhubo.put(e.getPlayer(),1); LiveAdminGui.offline_zhubo.put(e.getPlayer(), 1);
String type = "信息"; String type = "信息";
String audience = e.getUser().nickName(); String audience = e.getUser().nickName();
String message = e.getContent(); String message = e.getContent();
Bukkit.getConsoleSender().sendMessage("[直播互动 "+e.getPlayer().getName()+"] 类型: " + type + " 用户: " + audience + " 信息: " + message); Bukkit.getConsoleSender().sendMessage("[直播互动 " + e.getPlayer().getName() + "] 类型: " + type + " 用户: " + audience + " 信息: " + message);
} }
@EventHandler//点赞 @EventHandler//点赞
public void onGuanzhu(LiveLikeEvents e) { public void onGuanzhu(LiveLikeEvents e) {
LiveAdminGui.offline_zhubo.put(e.getPlayer(),1); LiveAdminGui.offline_zhubo.put(e.getPlayer(), 1);
String type = "点赞"; String type = "点赞";
String audience = e.getUser().nickName(); String audience = e.getUser().nickName();
long gift_amount = e.getCount(); long gift_amount = e.getCount();
@ -68,10 +71,10 @@ public class LiveEvent implements Listener {
@EventHandler//进入 @EventHandler//进入
public void onMcLive(LiveEnterEvents e) { public void onMcLive(LiveEnterEvents e) {
Player player = e.getPlayer(); Player player = e.getPlayer();
LiveAdminGui.offline_zhubo.put(e.getPlayer(),1); LiveAdminGui.offline_zhubo.put(e.getPlayer(), 1);
String type = "进入"; String type = "进入";
String audience = e.getUser().nickName(); String audience = e.getUser().nickName();
Bukkit.getConsoleSender().sendMessage("[直播互动 "+e.getPlayer().getName()+"] 类型: " + type + " 用户: " + audience); Bukkit.getConsoleSender().sendMessage("[直播互动 " + e.getPlayer().getName() + "] 类型: " + type + " 用户: " + audience);
player.spigot().sendMessage(ChatMessageType.ACTION_BAR,new TextComponent("§6" + Main.HideName(audience) + "来了")); player.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent("§6" + Main.HideName(audience) + "来了"));
} }
} }

View File

@ -10,15 +10,15 @@ import org.bukkit.event.Listener;
public class ModEvent implements Listener { public class ModEvent implements Listener {
@EventHandler @EventHandler
public void onWsMessage(WSMessageEvent e){ public void onWsMessage(WSMessageEvent e) {
Player player = e.getPlayer(); Player player = e.getPlayer();
String s = e.getMessage(); String s = e.getMessage();
MessageUtil.parse(player,s); MessageUtil.parse(player, s);
} }
@EventHandler @EventHandler
public void onKey(KeyInputEvent e){ public void onKey(KeyInputEvent e) {
Player player = e.getPlayer(); Player player = e.getPlayer();
} }
} }

View File

@ -21,13 +21,13 @@ public class ConfigYml {
} }
this.MainDebug = yml.getBoolean("MainDebug"); this.MainDebug = yml.getBoolean("MainDebug");
this.GameMode = yml.getString("GameMode"); this.GameMode = yml.getString("GameMode");
Bukkit.getConsoleSender().sendMessage("§b[整蛊MC直播] §7对接游戏: §e"+ this.GameMode); Bukkit.getConsoleSender().sendMessage("§b[整蛊MC直播] §7对接游戏: §e" + this.GameMode);
if (yml.getConfigurationSection("LiveId") != null) { if (yml.getConfigurationSection("LiveId") != null) {
HashMap<String, String> hashMap = new HashMap<>(); HashMap<String, String> hashMap = new HashMap<>();
for (String playName : yml.getConfigurationSection("LiveId").getKeys(false)) { for (String playName : yml.getConfigurationSection("LiveId").getKeys(false)) {
String live_id = yml.getString("LiveId." + playName); String live_id = yml.getString("LiveId." + playName);
hashMap.put(playName, live_id); hashMap.put(playName, live_id);
Bukkit.getConsoleSender().sendMessage("§b[整蛊MC直播] §7主播: §e"+ playName + " - " + live_id); Bukkit.getConsoleSender().sendMessage("§b[整蛊MC直播] §7主播: §e" + playName + " - " + live_id);
} }
this.RoomId_Map = hashMap; this.RoomId_Map = hashMap;
} }
@ -54,21 +54,28 @@ public class ConfigYml {
Main.plugin.saveConfig(); Main.plugin.saveConfig();
} }
public boolean isMainDebug() {return MainDebug;} public boolean isMainDebug() {
return MainDebug;
}
public void setMainDebug(boolean butt) { public void setMainDebug(boolean butt) {
FileConfiguration yml = Main.plugin.getConfig(); FileConfiguration yml = Main.plugin.getConfig();
yml.set("MainDebug",butt); yml.set("MainDebug", butt);
Main.plugin.saveConfig(); Main.plugin.saveConfig();
MainDebug = butt; MainDebug = butt;
} }
public long getGifts_delay() {return gifts_delay;} public long getGifts_delay() {
return gifts_delay;
}
public void setGifts_delay(long gifts_delay) { public void setGifts_delay(long gifts_delay) {
FileConfiguration yml = Main.plugin.getConfig(); FileConfiguration yml = Main.plugin.getConfig();
yml.set("GiftDelay",gifts_delay); yml.set("GiftDelay", gifts_delay);
Main.plugin.saveConfig(); Main.plugin.saveConfig();
this.gifts_delay = gifts_delay; this.gifts_delay = gifts_delay;
} }
public String getGameMode() { public String getGameMode() {
return this.GameMode; return this.GameMode;
} }
@ -83,8 +90,9 @@ public class ConfigYml {
public HashMap<String, String> getRoomId_Map() { public HashMap<String, String> getRoomId_Map() {
return this.RoomId_Map; return this.RoomId_Map;
} }
public void setRoomId(String playName, String roomId) { public void setRoomId(String playName, String roomId) {
this.RoomId_Map.put(playName,roomId); this.RoomId_Map.put(playName, roomId);
} }
} }

View File

@ -0,0 +1,34 @@
package com.io.yutian.mclive.util;
import java.io.*;
import java.net.URL;
import java.util.Base64;
public class FileUtil {
public static void downloadImage(String imageUrl, File destinationFile, Runnable callback) {
try (InputStream inputStream = new URL(imageUrl).openStream();
OutputStream outputStream = new FileOutputStream(destinationFile)) {
byte[] buffer = new byte[2048];
int length;
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
}
callback.run();
} catch (IOException e) {
e.printStackTrace();
}
}
public static String convertImageToBase64(File imageFile) {
try (FileInputStream fileInputStream = new FileInputStream(imageFile)) {
byte[] imageBytes = new byte[(int) imageFile.length()];
fileInputStream.read(imageBytes);
return Base64.getEncoder().encodeToString(imageBytes);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}

View File

@ -1,13 +1,21 @@
package com.io.yutian.mclive.util; package com.io.yutian.mclive.util;
import cn.hamster3.cdapi.CDTimeAPI; import cn.hamster3.cdapi.CDTimeAPI;
import com.io.yutian.livemutually.manager.GiftData; import com.io.yutian.livemutually.manager.GiftManager;
import com.io.yutian.livemutually.manager.UserData; import com.io.yutian.livemutually.manager.RankManager;
import com.io.yutian.livemutually.wss.*; import com.io.yutian.livemutually.manager.UserManager;
import com.io.yutian.mclive.data.GiftData;
import com.io.yutian.mclive.data.UserData;
import com.io.yutian.livemutually.wss.KSAPILiveRoomWatcher;
import com.io.yutian.livemutually.wss.KuaiShouChat;
import com.io.yutian.livemutually.wss.KuaiShouLike;
import com.io.yutian.livemutually.wss.KuaiShouUser;
import com.io.yutian.mclive.Main; import com.io.yutian.mclive.Main;
import com.io.yutian.mclive.data.UserResourceData;
import com.io.yutian.mclive.event.LiveGiftEvents; import com.io.yutian.mclive.event.LiveGiftEvents;
import com.io.yutian.mclive.event.ZhuboAPI; import com.io.yutian.mclive.event.ZhuboAPI;
import com.io.yutian.verify.AESUtil; import com.io.yutian.verify.AESUtil;
import json.JSONArray;
import json.JSONObject; import json.JSONObject;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -19,18 +27,24 @@ import java.util.HashMap;
public class MessageUtil { public class MessageUtil {
public static void parse(Player player,String py_data){ // H8dyaR95ZJwZ6PikZ1qmoIY1 密匙
if(py_data.isEmpty()){return;} private static final String AES_KEY = "01001000001110000110010001111001011000010101001000111001001101010101101001001010011101110101101000110110010100000110100101101"; // 与Python中相同的密钥
if(ZhuboAPI.getRoomLiveName().equalsIgnoreCase("KuaiShou")){ public static HashMap<String, UserData> userDataMap = new HashMap<>();
public static void parse(Player player, String py_data) {
if (py_data.isEmpty()) {
return;
}
if (ZhuboAPI.getRoomLiveName().equalsIgnoreCase("KuaiShou")) {
JSONObject jsonObject = new JSONObject(py_data); JSONObject jsonObject = new JSONObject(py_data);
if (py_data.contains("type")) { if (py_data.contains("type")) {
long cdTime = CDTimeAPI.getCD(player.getUniqueId(),"tingcloud_cd"); long cdTime = CDTimeAPI.getCD(player.getUniqueId(), "tingcloud_cd");
if(cdTime < 0) { if (cdTime < 0) {
CDTimeAPI.setPlayerCD(player.getUniqueId(),"tingcloud_cd",1000 * 10); CDTimeAPI.setPlayerCD(player.getUniqueId(), "tingcloud_cd", 1000 * 10);
Bukkit.getConsoleSender().sendMessage("§a[直播连接助手] 听云整蛊弹幕正常抓取中..."); Bukkit.getConsoleSender().sendMessage("§a[直播连接助手] 听云整蛊弹幕正常抓取中...");
} }
String type = jsonObject.getString("type"); String type = jsonObject.getString("type");
if(type.equalsIgnoreCase("礼物")){ if (type.equalsIgnoreCase("礼物")) {
String nickName = jsonObject.getString("昵称"); String nickName = jsonObject.getString("昵称");
String giftName = jsonObject.getString("礼物名称"); String giftName = jsonObject.getString("礼物名称");
int newCount = jsonObject.getInt("礼物数量"); int newCount = jsonObject.getInt("礼物数量");
@ -48,26 +62,27 @@ public class MessageUtil {
String message = "§6[日志 - 礼物触发] §f" + player.getName() + " >>> " + nickName + " = §a" + giftName + " 数量: " + count_color + newCount; String message = "§6[日志 - 礼物触发] §f" + player.getName() + " >>> " + nickName + " = §a" + giftName + " 数量: " + count_color + newCount;
Bukkit.getConsoleSender().sendMessage(message); Bukkit.getConsoleSender().sendMessage(message);
LiveGiftEvents event = new LiveGiftEvents(player, new KuaiShouUser(nickName), giftName, newCount); LiveGiftEvents event = new LiveGiftEvents(player, new KuaiShouUser(nickName), giftName, newCount);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
} }
}else if(type.equalsIgnoreCase("发言")){ } else if (type.equalsIgnoreCase("发言")) {
String userName = jsonObject.getString("昵称"); String userName = jsonObject.getString("昵称");
String message = jsonObject.getString("弹幕"); String message = jsonObject.getString("弹幕");
KSAPILiveRoomWatcher ksapiLiveRoomWatcher = new KSAPILiveRoomWatcher(player); KSAPILiveRoomWatcher ksapiLiveRoomWatcher = new KSAPILiveRoomWatcher(player);
ksapiLiveRoomWatcher.callChat(new KuaiShouChat(userName, message)); ksapiLiveRoomWatcher.callChat(new KuaiShouChat(userName, message));
}else if(type.equalsIgnoreCase("点赞")){ } else if (type.equalsIgnoreCase("点赞")) {
String userName = jsonObject.getString("昵称"); String userName = jsonObject.getString("昵称");
KSAPILiveRoomWatcher ksapiLiveRoomWatcher = new KSAPILiveRoomWatcher(player); KSAPILiveRoomWatcher ksapiLiveRoomWatcher = new KSAPILiveRoomWatcher(player);
ksapiLiveRoomWatcher.callLike(new KuaiShouLike(userName, 1)); ksapiLiveRoomWatcher.callLike(new KuaiShouLike(userName, 1));
} }
} else { } else {
long cdTime = CDTimeAPI.getCD(player.getUniqueId(),"tingcloud_cd"); long cdTime = CDTimeAPI.getCD(player.getUniqueId(), "tingcloud_cd");
if(cdTime < 0) { if (cdTime < 0) {
CDTimeAPI.setPlayerCD(player.getUniqueId(),"tingcloud_cd",1000 * 10); CDTimeAPI.setPlayerCD(player.getUniqueId(), "tingcloud_cd", 1000 * 10);
Bukkit.getConsoleSender().sendMessage("§a[直播连接助手] 听云整蛊弹幕正常抓取中..."); Bukkit.getConsoleSender().sendMessage("§a[直播连接助手] 听云整蛊弹幕正常抓取中...");
} }
} }
}else { } else {
String s; String s;
try { try {
s = decrypt_ecb(py_data); s = decrypt_ecb(py_data);
@ -82,7 +97,10 @@ public class MessageUtil {
return; return;
} }
JSONObject dataObject = new JSONObject(jsonObject.getString("data")); JSONObject dataObject = new JSONObject(jsonObject.getString("data"));
String nickName = dataObject.getJSONObject("user").getString("nickName"); JSONObject userJSONObject = dataObject.getJSONObject("user");
String nickName = userJSONObject.getString("nickName");
UserResourceData userResourceData = parseUserResourceData(userJSONObject);
UserManager.setUserResourceData(nickName, userResourceData);
// 礼物名 // 礼物名
String giftName = dataObject.getJSONObject("gift").getString("name"); String giftName = dataObject.getJSONObject("gift").getString("name");
// 礼物数量 // 礼物数量
@ -138,6 +156,7 @@ public class MessageUtil {
Bukkit.getConsoleSender().sendMessage(message); Bukkit.getConsoleSender().sendMessage(message);
LiveGiftEvents event = new LiveGiftEvents(player, new KuaiShouUser(nickName), giftName, newCount); LiveGiftEvents event = new LiveGiftEvents(player, new KuaiShouUser(nickName), giftName, newCount);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);
RankManager.addUserAmount(nickName, Main.giftManager.getGiftMoney(giftName) * newCount);
} }
} else if (type.equalsIgnoreCase("chat_message")) { } else if (type.equalsIgnoreCase("chat_message")) {
if (!ZhuboAPI.isWsRoomIdSame(player)) { if (!ZhuboAPI.isWsRoomIdSame(player)) {
@ -171,7 +190,7 @@ public class MessageUtil {
ksapiLiveRoomWatcher.callUser(new KuaiShouUser(nickName)); ksapiLiveRoomWatcher.callUser(new KuaiShouUser(nickName));
} else if (type.equalsIgnoreCase("live_id")) { } else if (type.equalsIgnoreCase("live_id")) {
JSONObject dataObject = jsonObject.getJSONObject("data"); JSONObject dataObject = jsonObject.getJSONObject("data");
String wsRoomId = dataObject.getString("id").replace(" ","").replace("\n",""); String wsRoomId = dataObject.getString("id").replace(" ", "").replace("\n", "");
if (ZhuboAPI.wsRoomIdSame.get(player) == null) { if (ZhuboAPI.wsRoomIdSame.get(player) == null) {
String roomId = Main.configYml.getRoomId(player.getName()); String roomId = Main.configYml.getRoomId(player.getName());
if (!wsRoomId.equalsIgnoreCase(roomId)) { if (!wsRoomId.equalsIgnoreCase(roomId)) {
@ -192,21 +211,35 @@ public class MessageUtil {
public static void sendConsoleMessage(String message) { public static void sendConsoleMessage(String message) {
// Bukkit.getConsoleSender().sendMessage("§6[弹幕监听] " + message); // Bukkit.getConsoleSender().sendMessage("§6[弹幕监听] " + message);
} }
public static HashMap<String, UserData> userDataMap = new HashMap<>();
// H8dyaR95ZJwZ6PikZ1qmoIY1 密匙
private static final String AES_KEY = "01001000001110000110010001111001011000010101001000111001001101010101101001001010011101110101101000110110010100000110100101101"; // 与Python中相同的密钥
public static String decrypt_ecb(String encryptedMessage) throws Exception { public static String decrypt_ecb(String encryptedMessage) throws Exception {
// Base64解码 // Base64解码
byte[] decodedMessage = Base64.getDecoder().decode(encryptedMessage); byte[] decodedMessage = Base64.getDecoder().decode(encryptedMessage);
// AES解密 // AES解密
Cipher cipher = Cipher.getInstance(AESUtil.convertString("0100000101000101010100110010111101000101010000110100001000101111010100000100"+AESUtil.DEFAULT_CIPHER_ALGORITHM)); Cipher cipher = Cipher.getInstance(AESUtil.convertString("0100000101000101010100110010111101000101010000110100001000101111010100000100" + AESUtil.DEFAULT_CIPHER_ALGORITHM));
SecretKeySpec secretKeySpec = new SecretKeySpec(AESUtil.convertString(AES_KEY+"0110101101000110001011100010110110101101111010010010101100100110001").getBytes(), "AES"); SecretKeySpec secretKeySpec = new SecretKeySpec(AESUtil.convertString(AES_KEY + "0110101101000110001011100010110110101101111010010010101100100110001").getBytes(), "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] decryptedBytes = cipher.doFinal(decodedMessage); byte[] decryptedBytes = cipher.doFinal(decodedMessage);
// 转换为字符串 // 转换为字符串
return new String(decryptedBytes, "UTF-8"); return new String(decryptedBytes, "UTF-8");
} }
private static UserResourceData parseUserResourceData(JSONObject jsonObject) {
String nickname = jsonObject.getString("nickName");
String avatarThumb = jsonObject.getJSONObject("AvatarThumb").getJSONArray("urlListList").getString(0);
int level = 1;
if (jsonObject.has("BadgeImageList")) {
JSONArray jsonArray = jsonObject.getJSONArray("BadgeImageList");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
String url = jsonObject1.getString("uri");
if (url.startsWith("webcast/new_user_grade_level")) {
level = jsonObject1.getJSONObject("content").getInt("level");
}
}
}
return new UserResourceData(nickname, avatarThumb, level);
}
} }

View File

@ -26,9 +26,9 @@ public class SqlUtil extends MegumiSQL {
public void openConnection() { public void openConnection() {
try { try {
String mcVersion = Main.getMinecraftVersion(); String mcVersion = Main.getMinecraftVersion();
if(mcVersion.contains("1_20")){ if (mcVersion.contains("1_20")) {
Class.forName("com.mysql.cj.jdbc.Driver"); // 1.20.4的mysql路径 Class.forName("com.mysql.cj.jdbc.Driver"); // 1.20.4的mysql路径
}else{ } else {
Class.forName("com.mysql.jdbc.Driver"); // 1.18.2的mysql路径 Class.forName("com.mysql.jdbc.Driver"); // 1.18.2的mysql路径
} }
this.connection = DriverManager.getConnection("jdbc:mysql://" + this.hostname + ":" + this.port + "/" + this.database + "?useSSL=false", this.username, this.password); this.connection = DriverManager.getConnection("jdbc:mysql://" + this.hostname + ":" + this.port + "/" + this.database + "?useSSL=false", this.username, this.password);

View File

@ -14,9 +14,9 @@ import java.util.Base64;
public class AESUtil { public class AESUtil {
private static final String KEY_ALGORITHM = "AES";
// AES/ECB/PKCS5Padding // AES/ECB/PKCS5Padding
public static final String DEFAULT_CIPHER_ALGORITHM = "101101000011010100110011010101010000011000010110010001100100011010010110111001100111"; public static final String DEFAULT_CIPHER_ALGORITHM = "101101000011010100110011010101010000011000010110010001100100011010010110111001100111";
private static final String KEY_ALGORITHM = "AES";
// 将二进制字符串转换为普通字符串 // 将二进制字符串转换为普通字符串
public static String convertString(String binaryString) { public static String convertString(String binaryString) {
@ -34,25 +34,23 @@ public class AESUtil {
return result.toString(); return result.toString();
} }
public static boolean isVerifyCheck(Player p, String pluginName, String roomId){ public static boolean isVerifyCheck(Player p, String pluginName, String roomId) {
if(!Main.check_plugin){ if (!Main.check_plugin) {
return false; return false;
} }
PluginVerifyResult verifyResult = VerifyHandler.verify("127.0.0.1",pluginName,roomId); PluginVerifyResult verifyResult = VerifyHandler.verify("127.0.0.1", pluginName, roomId);
if (!verifyResult.equals(PluginVerifyResult.VERIFY_SUCCESS)) { if (!verifyResult.equals(PluginVerifyResult.VERIFY_SUCCESS)) {
if(verifyResult == PluginVerifyResult.USER_STATE_DISABLE){ if (verifyResult == PluginVerifyResult.USER_STATE_DISABLE) {
Bukkit.getConsoleSender().sendMessage("[验证日志 - 拦截] "+p.getName()+" 的直播间授权已到期."); Bukkit.getConsoleSender().sendMessage("[验证日志 - 拦截] " + p.getName() + " 的直播间授权已到期.");
p.sendMessage("§c[系统]§a验证尚未通过,您的直播间授权已到期."); p.sendMessage("§c[系统]§a验证尚未通过,您的直播间授权已到期.");
} else } else if (verifyResult == PluginVerifyResult.FAIL_CODE) {
if(verifyResult == PluginVerifyResult.FAIL_CODE){ Bukkit.getConsoleSender().sendMessage("[验证日志 - 拦截] " + p.getName() + " 的直播间尚未进行授权. " + roomId);
Bukkit.getConsoleSender().sendMessage("[验证日志 - 拦截] "+p.getName()+" 的直播间尚未进行授权. "+roomId); p.sendMessage("§c[系统]§a验证尚未通过,直播间§e<" + roomId + ">§a尚未进行授权.");
p.sendMessage("§c[系统]§a验证尚未通过,直播间§e<"+roomId+">§a尚未进行授权."); } else if (verifyResult == PluginVerifyResult.FAIL_TIMEOUT) {
} else Bukkit.getConsoleSender().sendMessage("[验证日志 - 拦截] " + p.getName() + " 的本地网络有问题,无法连接验证服务器.");
if(verifyResult == PluginVerifyResult.FAIL_TIMEOUT){
Bukkit.getConsoleSender().sendMessage("[验证日志 - 拦截] "+p.getName()+" 的本地网络有问题,无法连接验证服务器.");
p.sendMessage("§c[系统]§a验证尚未通过,您当前的网络环境有问题."); p.sendMessage("§c[系统]§a验证尚未通过,您当前的网络环境有问题.");
} else { } else {
Bukkit.getConsoleSender().sendMessage("[验证日志 - 拦截] "+p.getName()+" 的无法通过验证. "+verifyResult); Bukkit.getConsoleSender().sendMessage("[验证日志 - 拦截] " + p.getName() + " 的无法通过验证. " + verifyResult);
p.sendMessage("§c[系统]§a验证尚未通过,无法连接直播间,请联系管理员。§c§l#" + verifyResult); p.sendMessage("§c[系统]§a验证尚未通过,无法连接直播间,请联系管理员。§c§l#" + verifyResult);
} }
return true; return true;
@ -68,7 +66,7 @@ public class AESUtil {
public static String encrypt(String content, String key) { public static String encrypt(String content, String key) {
try { try {
Cipher cipher = Cipher.getInstance(convertString("0100000101000101010100110010111101000101010000110100001000101111010100000100"+DEFAULT_CIPHER_ALGORITHM)); Cipher cipher = Cipher.getInstance(convertString("0100000101000101010100110010111101000101010000110100001000101111010100000100" + DEFAULT_CIPHER_ALGORITHM));
byte[] byteContent = content.getBytes("utf-8"); byte[] byteContent = content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key)); cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(key));
byte[] result = cipher.doFinal(byteContent); byte[] result = cipher.doFinal(byteContent);
@ -80,7 +78,7 @@ public class AESUtil {
public static String decrypt(String content, String key) { public static String decrypt(String content, String key) {
try { try {
Cipher cipher = Cipher.getInstance(convertString("0100000101000101010100110010111101000101010000110100001000101111010100000100"+DEFAULT_CIPHER_ALGORITHM)); Cipher cipher = Cipher.getInstance(convertString("0100000101000101010100110010111101000101010000110100001000101111010100000100" + DEFAULT_CIPHER_ALGORITHM));
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key)); cipher.init(Cipher.DECRYPT_MODE, getSecretKey(key));
byte[] result = cipher.doFinal(base642Byte(content)); byte[] result = cipher.doFinal(base642Byte(content));
return new String(result, "utf-8"); return new String(result, "utf-8");

View File

@ -4,7 +4,6 @@ import json.JSONObject;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
@ -41,24 +40,26 @@ public class VerifyHandler {
return PluginVerifyResult.UNKNOWN; return PluginVerifyResult.UNKNOWN;
} }
} }
public static String getServerIp(){
public static String getServerIp() {
String a = "47."; String a = "47.";
String b = "111."; String b = "111.";
String c = "169."; String c = "169.";
String d = "142"; String d = "142";
String e = "82"; String e = "82";
String f = "81"; String f = "81";
return a+b+c+d+":"+e+f; return a + b + c + d + ":" + e + f;
} }
private static String get(String plugin, String code) throws Exception { private static String get(String plugin, String code) throws Exception {
String url = "/verify?plugin="+plugin+"&code="+code; String url = "/verify?plugin=" + plugin + "&code=" + code;
URL realUrl = new URL("http://"+getServerIp()+url); URL realUrl = new URL("http://" + getServerIp() + url);
URLConnection connection = realUrl.openConnection(); URLConnection connection = realUrl.openConnection();
connection.setConnectTimeout(5000); connection.setConnectTimeout(5000);
connection.setReadTimeout(15000); connection.setReadTimeout(15000);
connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
connection.connect(); connection.connect();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8")); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();

File diff suppressed because it is too large Load Diff

View File

@ -7,14 +7,15 @@ package json;
* @version 2015-12-09 * @version 2015-12-09
*/ */
public class JSONException extends RuntimeException { public class JSONException extends RuntimeException {
/** Serialization ID */ /**
* Serialization ID
*/
private static final long serialVersionUID = 0; private static final long serialVersionUID = 0;
/** /**
* Constructs a JSONException with an explanatory message. * Constructs a JSONException with an explanatory message.
* *
* @param message * @param message Detail about the reason for the exception.
* Detail about the reason for the exception.
*/ */
public JSONException(final String message) { public JSONException(final String message) {
super(message); super(message);
@ -23,10 +24,8 @@ public class JSONException extends RuntimeException {
/** /**
* Constructs a JSONException with an explanatory message and cause. * Constructs a JSONException with an explanatory message and cause.
* *
* @param message * @param message Detail about the reason for the exception.
* Detail about the reason for the exception. * @param cause The cause.
* @param cause
* The cause.
*/ */
public JSONException(final String message, final Throwable cause) { public JSONException(final String message, final Throwable cause) {
super(message, cause); super(message, cause);
@ -35,8 +34,7 @@ public class JSONException extends RuntimeException {
/** /**
* Constructs a new JSONException with the specified cause. * Constructs a new JSONException with the specified cause.
* *
* @param cause * @param cause The cause.
* The cause.
*/ */
public JSONException(final Throwable cause) { public JSONException(final Throwable cause) {
super(cause.getMessage(), cause); super(cause.getMessage(), cause);

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,7 @@ SOFTWARE.
/** /**
* A JSON Pointer is a simple query language defined for JSON documents by * A JSON Pointer is a simple query language defined for JSON documents by
* <a href="https://tools.ietf.org/html/rfc6901">RFC 6901</a>. * <a href="https://tools.ietf.org/html/rfc6901">RFC 6901</a>.
* * <p>
* In a nutshell, JSONPointer allows the user to navigate into a JSON document * In a nutshell, JSONPointer allows the user to navigate into a JSON document
* using strings, and retrieve targeted objects, like a simple form of XPATH. * using strings, and retrieve targeted objects, like a simple form of XPATH.
* Path segments are separated by the '/' char, which signifies the root of * Path segments are separated by the '/' char, which signifies the root of
@ -55,76 +55,6 @@ public class JSONPointer {
// used for URL encoding and decoding // used for URL encoding and decoding
private static final String ENCODING = "utf-8"; private static final String ENCODING = "utf-8";
/**
* This class allows the user to build a JSONPointer in steps, using
* exactly one segment in each step.
*/
public static class Builder {
// Segments for the eventual JSONPointer string
private final List<String> refTokens = new ArrayList<String>();
/**
* Creates a {@code JSONPointer} instance using the tokens previously set using the
* {@link #append(String)} method calls.
*/
public JSONPointer build() {
return new JSONPointer(this.refTokens);
}
/**
* Adds an arbitrary token to the list of reference tokens. It can be any non-null value.
*
* Unlike in the case of JSON string or URI fragment representation of JSON pointers, the
* argument of this method MUST NOT be escaped. If you want to query the property called
* {@code "a~b"} then you should simply pass the {@code "a~b"} string as-is, there is no
* need to escape it as {@code "a~0b"}.
*
* @param token the new token to be appended to the list
* @return {@code this}
* @throws NullPointerException if {@code token} is null
*/
public Builder append(String token) {
if (token == null) {
throw new NullPointerException("token cannot be null");
}
this.refTokens.add(token);
return this;
}
/**
* Adds an integer to the reference token list. Although not necessarily, mostly this token will
* denote an array index.
*
* @param arrayIndex the array index to be added to the token list
* @return {@code this}
*/
public Builder append(int arrayIndex) {
this.refTokens.add(String.valueOf(arrayIndex));
return this;
}
}
/**
* Static factory method for {@link Builder}. Example usage:
*
* <pre><code>
* JSONPointer pointer = JSONPointer.builder()
* .append("obj")
* .append("other~key").append("another/key")
* .append("\"")
* .append(0)
* .build();
* </code></pre>
*
* @return a builder instance which can be used to construct a {@code JSONPointer} instance by chained
* {@link Builder#append(String)} calls.
*/
public static Builder builder() {
return new Builder();
}
// Segments for the JSONPointer string // Segments for the JSONPointer string
private final List<String> refTokens; private final List<String> refTokens;
@ -163,7 +93,7 @@ public class JSONPointer {
do { do {
prevSlashIdx = slashIdx + 1; prevSlashIdx = slashIdx + 1;
slashIdx = refs.indexOf('/', prevSlashIdx); slashIdx = refs.indexOf('/', prevSlashIdx);
if(prevSlashIdx == slashIdx || prevSlashIdx == refs.length()) { if (prevSlashIdx == slashIdx || prevSlashIdx == refs.length()) {
// found 2 slashes in a row ( obj//next ) // found 2 slashes in a row ( obj//next )
// or single slash at the end of a string ( obj/test/ ) // or single slash at the end of a string ( obj/test/ )
this.refTokens.add(""); this.refTokens.add("");
@ -186,12 +116,73 @@ public class JSONPointer {
this.refTokens = new ArrayList<String>(refTokens); this.refTokens = new ArrayList<String>(refTokens);
} }
/**
* Static factory method for {@link Builder}. Example usage:
*
* <pre><code>
* JSONPointer pointer = JSONPointer.builder()
* .append("obj")
* .append("other~key").append("another/key")
* .append("\"")
* .append(0)
* .build();
* </code></pre>
*
* @return a builder instance which can be used to construct a {@code JSONPointer} instance by chained
* {@link Builder#append(String)} calls.
*/
public static Builder builder() {
return new Builder();
}
private static String unescape(String token) { private static String unescape(String token) {
return token.replace("~1", "/").replace("~0", "~") return token.replace("~1", "/").replace("~0", "~")
.replace("\\\"", "\"") .replace("\\\"", "\"")
.replace("\\\\", "\\"); .replace("\\\\", "\\");
} }
/**
* Matches a JSONArray element by ordinal position
*
* @param current the JSONArray to be evaluated
* @param indexToken the array index in string form
* @return the matched object. If no matching item is found a
* @throws JSONPointerException is thrown if the index is out of bounds
*/
private static Object readByIndexToken(Object current, String indexToken) throws JSONPointerException {
try {
int index = Integer.parseInt(indexToken);
JSONArray currentArr = (JSONArray) current;
if (index >= currentArr.length()) {
throw new JSONPointerException(format("index %s is out of bounds - the array has %d elements", indexToken,
Integer.valueOf(currentArr.length())));
}
try {
return currentArr.get(index);
} catch (JSONException e) {
throw new JSONPointerException("Error reading value at index position " + index, e);
}
} catch (NumberFormatException e) {
throw new JSONPointerException(format("%s is not an array index", indexToken), e);
}
}
/**
* Escapes path segment values to an unambiguous form.
* The escape char to be inserted is '~'. The chars to be escaped
* are ~, which maps to ~0, and /, which maps to ~1. Backslashes
* and double quote chars are also escaped.
*
* @param token the JSONPointer segment value to be escaped
* @return the escaped value for the token
*/
private static String escape(String token) {
return token.replace("~", "~0")
.replace("/", "~1")
.replace("\\", "\\\\")
.replace("\"", "\\\"");
}
/** /**
* Evaluates this JSON Pointer on the given {@code document}. The {@code document} * Evaluates this JSON Pointer on the given {@code document}. The {@code document}
* is usually a {@link JSONObject} or a {@link JSONArray} instance, but the empty * is usually a {@link JSONObject} or a {@link JSONArray} instance, but the empty
@ -221,31 +212,6 @@ public class JSONPointer {
return current; return current;
} }
/**
* Matches a JSONArray element by ordinal position
* @param current the JSONArray to be evaluated
* @param indexToken the array index in string form
* @return the matched object. If no matching item is found a
* @throws JSONPointerException is thrown if the index is out of bounds
*/
private static Object readByIndexToken(Object current, String indexToken) throws JSONPointerException {
try {
int index = Integer.parseInt(indexToken);
JSONArray currentArr = (JSONArray) current;
if (index >= currentArr.length()) {
throw new JSONPointerException(format("index %s is out of bounds - the array has %d elements", indexToken,
Integer.valueOf(currentArr.length())));
}
try {
return currentArr.get(index);
} catch (JSONException e) {
throw new JSONPointerException("Error reading value at index position " + index, e);
}
} catch (NumberFormatException e) {
throw new JSONPointerException(format("%s is not an array index", indexToken), e);
}
}
/** /**
* Returns a string representing the JSONPointer path value using string * Returns a string representing the JSONPointer path value using string
* representation * representation
@ -253,27 +219,12 @@ public class JSONPointer {
@Override @Override
public String toString() { public String toString() {
StringBuilder rval = new StringBuilder(""); StringBuilder rval = new StringBuilder("");
for (String token: this.refTokens) { for (String token : this.refTokens) {
rval.append('/').append(escape(token)); rval.append('/').append(escape(token));
} }
return rval.toString(); return rval.toString();
} }
/**
* Escapes path segment values to an unambiguous form.
* The escape char to be inserted is '~'. The chars to be escaped
* are ~, which maps to ~0, and /, which maps to ~1. Backslashes
* and double quote chars are also escaped.
* @param token the JSONPointer segment value to be escaped
* @return the escaped value for the token
*/
private static String escape(String token) {
return token.replace("~", "~0")
.replace("/", "~1")
.replace("\\", "\\\\")
.replace("\"", "\\\"");
}
/** /**
* Returns a string representing the JSONPointer path value using URI * Returns a string representing the JSONPointer path value using URI
* fragment identifier representation * fragment identifier representation
@ -290,4 +241,54 @@ public class JSONPointer {
} }
} }
/**
* This class allows the user to build a JSONPointer in steps, using
* exactly one segment in each step.
*/
public static class Builder {
// Segments for the eventual JSONPointer string
private final List<String> refTokens = new ArrayList<String>();
/**
* Creates a {@code JSONPointer} instance using the tokens previously set using the
* {@link #append(String)} method calls.
*/
public JSONPointer build() {
return new JSONPointer(this.refTokens);
}
/**
* Adds an arbitrary token to the list of reference tokens. It can be any non-null value.
* <p>
* Unlike in the case of JSON string or URI fragment representation of JSON pointers, the
* argument of this method MUST NOT be escaped. If you want to query the property called
* {@code "a~b"} then you should simply pass the {@code "a~b"} string as-is, there is no
* need to escape it as {@code "a~0b"}.
*
* @param token the new token to be appended to the list
* @return {@code this}
* @throws NullPointerException if {@code token} is null
*/
public Builder append(String token) {
if (token == null) {
throw new NullPointerException("token cannot be null");
}
this.refTokens.add(token);
return this;
}
/**
* Adds an integer to the reference token list. Although not necessarily, mostly this token will
* denote an array index.
*
* @param arrayIndex the array index to be added to the token list
* @return {@code this}
*/
public Builder append(int arrayIndex) {
this.refTokens.add(String.valueOf(arrayIndex));
return this;
}
}
} }

View File

@ -40,4 +40,5 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* present at any level in the class hierarchy, then the method will * present at any level in the class hierarchy, then the method will
* not be serialized from the bean into the JSONObject. * not be serialized from the bean into the JSONObject.
*/ */
public @interface JSONPropertyIgnore { } public @interface JSONPropertyIgnore {
}

View File

@ -1,4 +1,5 @@
package json; package json;
/** /**
* The <code>JSONString</code> interface allows a <code>toJSONString()</code> * The <code>JSONString</code> interface allows a <code>toJSONString()</code>
* method so that a class can change the behavior of * method so that a class can change the behavior of

View File

@ -53,6 +53,7 @@ import java.io.StringWriter;
* you. Objects and arrays can be nested up to 20 levels deep. * you. Objects and arrays can be nested up to 20 levels deep.
* <p> * <p>
* This can sometimes be easier than using a JSONObject to build a string. * This can sometimes be easier than using a JSONObject to build a string.
*
* @author JSON.org * @author JSON.org
* @version 2015-12-09 * @version 2015-12-09
*/ */
@ -70,6 +71,7 @@ public class JSONStringer extends JSONWriter {
* problem in the construction of the JSON text (such as the calls to * problem in the construction of the JSON text (such as the calls to
* <code>array</code> were not properly balanced with calls to * <code>array</code> were not properly balanced with calls to
* <code>endArray</code>). * <code>endArray</code>).
*
* @return The JSON text. * @return The JSON text.
*/ */
@Override @Override

View File

@ -30,37 +30,54 @@ SOFTWARE.
* A JSONTokener takes a source string and extracts characters and tokens from * A JSONTokener takes a source string and extracts characters and tokens from
* it. It is used by the JSONObject and JSONArray constructors to parse * it. It is used by the JSONObject and JSONArray constructors to parse
* JSON source strings. * JSON source strings.
*
* @author JSON.org * @author JSON.org
* @version 2014-05-03 * @version 2014-05-03
*/ */
public class JSONTokener { public class JSONTokener {
/** current read character position on the current line. */ /**
private long character; * Reader for the input.
/** flag to indicate if the end of the input has been found. */ */
private boolean eof;
/** current read index of the input. */
private long index;
/** current line of the input. */
private long line;
/** previous character read from the input. */
private char previous;
/** Reader for the input. */
private final Reader reader; private final Reader reader;
/** flag to indicate that a previous character was requested. */ /**
* current read character position on the current line.
*/
private long character;
/**
* flag to indicate if the end of the input has been found.
*/
private boolean eof;
/**
* current read index of the input.
*/
private long index;
/**
* current line of the input.
*/
private long line;
/**
* previous character read from the input.
*/
private char previous;
/**
* flag to indicate that a previous character was requested.
*/
private boolean usePrevious; private boolean usePrevious;
/** the number of characters read in the previous line. */ /**
* the number of characters read in the previous line.
*/
private long characterPreviousLine; private long characterPreviousLine;
/** /**
* Construct a JSONTokener from a Reader. The caller must close the Reader. * Construct a JSONTokener from a Reader. The caller must close the Reader.
* *
* @param reader A reader. * @param reader A reader.
*/ */
public JSONTokener(Reader reader) { public JSONTokener(Reader reader) {
this.reader = reader.markSupported() this.reader = reader.markSupported()
? reader ? reader
: new BufferedReader(reader); : new BufferedReader(reader);
this.eof = false; this.eof = false;
this.usePrevious = false; this.usePrevious = false;
this.previous = 0; this.previous = 0;
@ -73,6 +90,7 @@ public class JSONTokener {
/** /**
* Construct a JSONTokener from an InputStream. The caller must close the input stream. * Construct a JSONTokener from an InputStream. The caller must close the input stream.
*
* @param inputStream The source. * @param inputStream The source.
*/ */
public JSONTokener(InputStream inputStream) { public JSONTokener(InputStream inputStream) {
@ -83,47 +101,18 @@ public class JSONTokener {
/** /**
* Construct a JSONTokener from a string. * Construct a JSONTokener from a string.
* *
* @param s A source string. * @param s A source string.
*/ */
public JSONTokener(String s) { public JSONTokener(String s) {
this(new StringReader(s)); this(new StringReader(s));
} }
/**
* Back up one character. This provides a sort of lookahead capability,
* so that you can test for a digit or letter before attempting to parse
* the next number or identifier.
* @throws JSONException Thrown if trying to step back more than 1 step
* or if already at the start of the string
*/
public void back() throws JSONException {
if (this.usePrevious || this.index <= 0) {
throw new JSONException("Stepping back two steps is not supported");
}
this.decrementIndexes();
this.usePrevious = true;
this.eof = false;
}
/**
* Decrements the indexes for the {@link #back()} method based on the previous character read.
*/
private void decrementIndexes() {
this.index--;
if(this.previous=='\r' || this.previous == '\n') {
this.line--;
this.character=this.characterPreviousLine ;
} else if(this.character > 0){
this.character--;
}
}
/** /**
* Get the hex value of a character (base16). * Get the hex value of a character (base16).
*
* @param c A character between '0' and '9' or between 'A' and 'F' or * @param c A character between '0' and '9' or between 'A' and 'F' or
* between 'a' and 'f'. * between 'a' and 'f'.
* @return An int between 0 and 15, or -1 if c was not a hex digit. * @return An int between 0 and 15, or -1 if c was not a hex digit.
*/ */
public static int dehexchar(char c) { public static int dehexchar(char c) {
if (c >= '0' && c <= '9') { if (c >= '0' && c <= '9') {
@ -138,6 +127,36 @@ public class JSONTokener {
return -1; return -1;
} }
/**
* Back up one character. This provides a sort of lookahead capability,
* so that you can test for a digit or letter before attempting to parse
* the next number or identifier.
*
* @throws JSONException Thrown if trying to step back more than 1 step
* or if already at the start of the string
*/
public void back() throws JSONException {
if (this.usePrevious || this.index <= 0) {
throw new JSONException("Stepping back two steps is not supported");
}
this.decrementIndexes();
this.usePrevious = true;
this.eof = false;
}
/**
* Decrements the indexes for the {@link #back()} method based on the previous character read.
*/
private void decrementIndexes() {
this.index--;
if (this.previous == '\r' || this.previous == '\n') {
this.line--;
this.character = this.characterPreviousLine;
} else if (this.character > 0) {
this.character--;
}
}
/** /**
* Checks if the end of the input has been reached. * Checks if the end of the input has been reached.
* *
@ -151,12 +170,13 @@ public class JSONTokener {
/** /**
* Determine if the source string still contains characters that next() * Determine if the source string still contains characters that next()
* can consume. * can consume.
*
* @return true if not yet at the end of the source. * @return true if not yet at the end of the source.
* @throws JSONException thrown if there is an error stepping forward * @throws JSONException thrown if there is an error stepping forward
* or backward while checking for more data. * or backward while checking for more data.
*/ */
public boolean more() throws JSONException { public boolean more() throws JSONException {
if(this.usePrevious) { if (this.usePrevious) {
return true; return true;
} }
try { try {
@ -166,7 +186,7 @@ public class JSONTokener {
} }
try { try {
// -1 is EOF, but next() can not consume the null character '\0' // -1 is EOF, but next() can not consume the null character '\0'
if(this.reader.read() <= 0) { if (this.reader.read() <= 0) {
this.eof = true; this.eof = true;
return false; return false;
} }
@ -208,21 +228,22 @@ public class JSONTokener {
/** /**
* Increments the internal indexes according to the previous character * Increments the internal indexes according to the previous character
* read and the character passed as the current character. * read and the character passed as the current character.
*
* @param c the current character read. * @param c the current character read.
*/ */
private void incrementIndexes(int c) { private void incrementIndexes(int c) {
if(c > 0) { if (c > 0) {
this.index++; this.index++;
if(c=='\r') { if (c == '\r') {
this.line++; this.line++;
this.characterPreviousLine = this.character; this.characterPreviousLine = this.character;
this.character=0; this.character = 0;
}else if (c=='\n') { } else if (c == '\n') {
if(this.previous != '\r') { if (this.previous != '\r') {
this.line++; this.line++;
this.characterPreviousLine = this.character; this.characterPreviousLine = this.character;
} }
this.character=0; this.character = 0;
} else { } else {
this.character++; this.character++;
} }
@ -232,6 +253,7 @@ public class JSONTokener {
/** /**
* Consume the next character, and check that it matches a specified * Consume the next character, and check that it matches a specified
* character. * character.
*
* @param c The character to match. * @param c The character to match.
* @return The character. * @return The character.
* @throws JSONException if the character does not match. * @throws JSONException if the character does not match.
@ -239,7 +261,7 @@ public class JSONTokener {
public char next(char c) throws JSONException { public char next(char c) throws JSONException {
char n = this.next(); char n = this.next();
if (n != c) { if (n != c) {
if(n > 0) { if (n > 0) {
throw this.syntaxError("Expected '" + c + "' and instead saw '" + throw this.syntaxError("Expected '" + c + "' and instead saw '" +
n + "'"); n + "'");
} }
@ -252,11 +274,10 @@ public class JSONTokener {
/** /**
* Get the next n characters. * Get the next n characters.
* *
* @param n The number of characters to take. * @param n The number of characters to take.
* @return A string of n characters. * @return A string of n characters.
* @throws JSONException * @throws JSONException Substring bounds error if there are not
* Substring bounds error if there are not * n characters remaining in the source string.
* n characters remaining in the source string.
*/ */
public String next(int n) throws JSONException { public String next(int n) throws JSONException {
if (n == 0) { if (n == 0) {
@ -279,11 +300,12 @@ public class JSONTokener {
/** /**
* Get the next char in the string, skipping whitespace. * Get the next char in the string, skipping whitespace.
*
* @return A character, or 0 if there are no more characters.
* @throws JSONException Thrown if there is an error reading the source string. * @throws JSONException Thrown if there is an error reading the source string.
* @return A character, or 0 if there are no more characters.
*/ */
public char nextClean() throws JSONException { public char nextClean() throws JSONException {
for (;;) { for (; ; ) {
char c = this.next(); char c = this.next();
if (c == 0 || c > ' ') { if (c == 0 || c > ' ') {
return c; return c;
@ -297,62 +319,63 @@ public class JSONTokener {
* Backslash processing is done. The formal JSON format does not * Backslash processing is done. The formal JSON format does not
* allow strings in single quotes, but an implementation is allowed to * allow strings in single quotes, but an implementation is allowed to
* accept them. * accept them.
*
* @param quote The quoting character, either * @param quote The quoting character, either
* <code>"</code>&nbsp;<small>(double quote)</small> or * <code>"</code>&nbsp;<small>(double quote)</small> or
* <code>'</code>&nbsp;<small>(single quote)</small>. * <code>'</code>&nbsp;<small>(single quote)</small>.
* @return A String. * @return A String.
* @throws JSONException Unterminated string. * @throws JSONException Unterminated string.
*/ */
public String nextString(char quote) throws JSONException { public String nextString(char quote) throws JSONException {
char c; char c;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (;;) { for (; ; ) {
c = this.next(); c = this.next();
switch (c) { switch (c) {
case 0: case 0:
case '\n': case '\n':
case '\r': case '\r':
throw this.syntaxError("Unterminated string"); throw this.syntaxError("Unterminated string");
case '\\': case '\\':
c = this.next(); c = this.next();
switch (c) { switch (c) {
case 'b': case 'b':
sb.append('\b'); sb.append('\b');
break; break;
case 't': case 't':
sb.append('\t'); sb.append('\t');
break; break;
case 'n': case 'n':
sb.append('\n'); sb.append('\n');
break; break;
case 'f': case 'f':
sb.append('\f'); sb.append('\f');
break; break;
case 'r': case 'r':
sb.append('\r'); sb.append('\r');
break; break;
case 'u': case 'u':
try { try {
sb.append((char)Integer.parseInt(this.next(4), 16)); sb.append((char) Integer.parseInt(this.next(4), 16));
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw this.syntaxError("Illegal escape.", e); throw this.syntaxError("Illegal escape.", e);
}
break;
case '"':
case '\'':
case '\\':
case '/':
sb.append(c);
break;
default:
throw this.syntaxError("Illegal escape.");
} }
break; break;
case '"':
case '\'':
case '\\':
case '/':
sb.append(c);
break;
default: default:
throw this.syntaxError("Illegal escape."); if (c == quote) {
} return sb.toString();
break; }
default: sb.append(c);
if (c == quote) {
return sb.toString();
}
sb.append(c);
} }
} }
} }
@ -361,14 +384,15 @@ public class JSONTokener {
/** /**
* Get the text up but not including the specified character or the * Get the text up but not including the specified character or the
* end of line, whichever comes first. * end of line, whichever comes first.
* @param delimiter A delimiter character. *
* @return A string. * @param delimiter A delimiter character.
* @return A string.
* @throws JSONException Thrown if there is an error while searching * @throws JSONException Thrown if there is an error while searching
* for the delimiter * for the delimiter
*/ */
public String nextTo(char delimiter) throws JSONException { public String nextTo(char delimiter) throws JSONException {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (;;) { for (; ; ) {
char c = this.next(); char c = this.next();
if (c == delimiter || c == 0 || c == '\n' || c == '\r') { if (c == delimiter || c == 0 || c == '\n' || c == '\r') {
if (c != 0) { if (c != 0) {
@ -384,15 +408,16 @@ public class JSONTokener {
/** /**
* Get the text up but not including one of the specified delimiter * Get the text up but not including one of the specified delimiter
* characters or the end of line, whichever comes first. * characters or the end of line, whichever comes first.
*
* @param delimiters A set of delimiter characters. * @param delimiters A set of delimiter characters.
* @return A string, trimmed. * @return A string, trimmed.
* @throws JSONException Thrown if there is an error while searching * @throws JSONException Thrown if there is an error while searching
* for the delimiter * for the delimiter
*/ */
public String nextTo(String delimiters) throws JSONException { public String nextTo(String delimiters) throws JSONException {
char c; char c;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (;;) { for (; ; ) {
c = this.next(); c = this.next();
if (delimiters.indexOf(c) >= 0 || c == 0 || if (delimiters.indexOf(c) >= 0 || c == 0 ||
c == '\n' || c == '\r') { c == '\n' || c == '\r') {
@ -409,24 +434,24 @@ public class JSONTokener {
/** /**
* Get the next value. The value can be a Boolean, Double, Integer, * Get the next value. The value can be a Boolean, Double, Integer,
* JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
* @throws JSONException If syntax error.
* *
* @return An object. * @return An object.
* @throws JSONException If syntax error.
*/ */
public Object nextValue() throws JSONException { public Object nextValue() throws JSONException {
char c = this.nextClean(); char c = this.nextClean();
String string; String string;
switch (c) { switch (c) {
case '"': case '"':
case '\'': case '\'':
return this.nextString(c); return this.nextString(c);
case '{': case '{':
this.back(); this.back();
return new JSONObject(this); return new JSONObject(this);
case '[': case '[':
this.back(); this.back();
return new JSONArray(this); return new JSONArray(this);
} }
/* /*
@ -458,11 +483,12 @@ public class JSONTokener {
/** /**
* Skip characters until the next character is the requested character. * Skip characters until the next character is the requested character.
* If the requested character is not found, no characters are skipped. * If the requested character is not found, no characters are skipped.
*
* @param to A character to skip to. * @param to A character to skip to.
* @return The requested character, or zero if the requested character * @return The requested character, or zero if the requested character
* is not found. * is not found.
* @throws JSONException Thrown if there is an error while searching * @throws JSONException Thrown if there is an error while searching
* for the to character * for the to character
*/ */
public char skipTo(char to) throws JSONException { public char skipTo(char to) throws JSONException {
char c; char c;
@ -496,7 +522,7 @@ public class JSONTokener {
* Make a JSONException to signal a syntax error. * Make a JSONException to signal a syntax error.
* *
* @param message The error message. * @param message The error message.
* @return A JSONException object, suitable for throwing * @return A JSONException object, suitable for throwing
*/ */
public JSONException syntaxError(String message) { public JSONException syntaxError(String message) {
return new JSONException(message + this.toString()); return new JSONException(message + this.toString());
@ -505,9 +531,9 @@ public class JSONTokener {
/** /**
* Make a JSONException to signal a syntax error. * Make a JSONException to signal a syntax error.
* *
* @param message The error message. * @param message The error message.
* @param causedBy The throwable that caused the error. * @param causedBy The throwable that caused the error.
* @return A JSONException object, suitable for throwing * @return A JSONException object, suitable for throwing
*/ */
public JSONException syntaxError(String message, Throwable causedBy) { public JSONException syntaxError(String message, Throwable causedBy) {
return new JSONException(message + this.toString(), causedBy); return new JSONException(message + this.toString(), causedBy);

View File

@ -54,18 +54,16 @@ SOFTWARE.
* you. Objects and arrays can be nested up to 200 levels deep. * you. Objects and arrays can be nested up to 200 levels deep.
* <p> * <p>
* This can sometimes be easier than using a JSONObject to build a string. * This can sometimes be easier than using a JSONObject to build a string.
*
* @author JSON.org * @author JSON.org
* @version 2016-08-08 * @version 2016-08-08
*/ */
public class JSONWriter { public class JSONWriter {
private static final int maxdepth = 200; private static final int maxdepth = 200;
/** /**
* The comma flag determines if a comma should be output before the next * The object/array stack.
* value.
*/ */
private boolean comma; private final JSONObject stack[];
/** /**
* The current mode. Values: * The current mode. Values:
* 'a' (array), * 'a' (array),
@ -75,21 +73,19 @@ public class JSONWriter {
* 'o' (object). * 'o' (object).
*/ */
protected char mode; protected char mode;
/**
* The object/array stack.
*/
private final JSONObject stack[];
/**
* The stack top index. A value of 0 indicates that the stack is empty.
*/
private int top;
/** /**
* The writer that will receive the output. * The writer that will receive the output.
*/ */
protected Appendable writer; protected Appendable writer;
/**
* The comma flag determines if a comma should be output before the next
* value.
*/
private boolean comma;
/**
* The stack top index. A value of 0 indicates that the stack is empty.
*/
private int top;
/** /**
* Make a fresh JSONWriter. It can be used to build one JSON text. * Make a fresh JSONWriter. It can be used to build one JSON text.
@ -102,200 +98,6 @@ public class JSONWriter {
this.writer = w; this.writer = w;
} }
/**
* Append a value.
* @param string A string value.
* @return this
* @throws JSONException If the value is out of sequence.
*/
private JSONWriter append(String string) throws JSONException {
if (string == null) {
throw new JSONException("Null pointer");
}
if (this.mode == 'o' || this.mode == 'a') {
try {
if (this.comma && this.mode == 'a') {
this.writer.append(',');
}
this.writer.append(string);
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
if (this.mode == 'o') {
this.mode = 'k';
}
this.comma = true;
return this;
}
throw new JSONException("Value out of sequence.");
}
/**
* Begin appending a new array. All values until the balancing
* <code>endArray</code> will be appended to this array. The
* <code>endArray</code> method must be called to mark the array's end.
* @return this
* @throws JSONException If the nesting is too deep, or if the object is
* started in the wrong place (for example as a key or after the end of the
* outermost array or object).
*/
public JSONWriter array() throws JSONException {
if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') {
this.push(null);
this.append("[");
this.comma = false;
return this;
}
throw new JSONException("Misplaced array.");
}
/**
* End something.
* @param m Mode
* @param c Closing character
* @return this
* @throws JSONException If unbalanced.
*/
private JSONWriter end(char m, char c) throws JSONException {
if (this.mode != m) {
throw new JSONException(m == 'a'
? "Misplaced endArray."
: "Misplaced endObject.");
}
this.pop(m);
try {
this.writer.append(c);
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
this.comma = true;
return this;
}
/**
* End an array. This method most be called to balance calls to
* <code>array</code>.
* @return this
* @throws JSONException If incorrectly nested.
*/
public JSONWriter endArray() throws JSONException {
return this.end('a', ']');
}
/**
* End an object. This method most be called to balance calls to
* <code>object</code>.
* @return this
* @throws JSONException If incorrectly nested.
*/
public JSONWriter endObject() throws JSONException {
return this.end('k', '}');
}
/**
* Append a key. The key will be associated with the next value. In an
* object, every value must be preceded by a key.
* @param string A key string.
* @return this
* @throws JSONException If the key is out of place. For example, keys
* do not belong in arrays or if the key is null.
*/
public JSONWriter key(String string) throws JSONException {
if (string == null) {
throw new JSONException("Null key.");
}
if (this.mode == 'k') {
try {
JSONObject topObject = this.stack[this.top - 1];
// don't use the built in putOnce method to maintain Android support
if(topObject.has(string)) {
throw new JSONException("Duplicate key \"" + string + "\"");
}
topObject.put(string, true);
if (this.comma) {
this.writer.append(',');
}
this.writer.append(JSONObject.quote(string));
this.writer.append(':');
this.comma = false;
this.mode = 'o';
return this;
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
}
throw new JSONException("Misplaced key.");
}
/**
* Begin appending a new object. All keys and values until the balancing
* <code>endObject</code> will be appended to this object. The
* <code>endObject</code> method must be called to mark the object's end.
* @return this
* @throws JSONException If the nesting is too deep, or if the object is
* started in the wrong place (for example as a key or after the end of the
* outermost array or object).
*/
public JSONWriter object() throws JSONException {
if (this.mode == 'i') {
this.mode = 'o';
}
if (this.mode == 'o' || this.mode == 'a') {
this.append("{");
this.push(new JSONObject());
this.comma = false;
return this;
}
throw new JSONException("Misplaced object.");
}
/**
* Pop an array or object scope.
* @param c The scope to close.
* @throws JSONException If nesting is wrong.
*/
private void pop(char c) throws JSONException {
if (this.top <= 0) {
throw new JSONException("Nesting error.");
}
char m = this.stack[this.top - 1] == null ? 'a' : 'k';
if (m != c) {
throw new JSONException("Nesting error.");
}
this.top -= 1;
this.mode = this.top == 0
? 'd'
: this.stack[this.top - 1] == null
? 'a'
: 'k';
}
/**
* Push an array or object scope.
* @param jo The scope to open.
* @throws JSONException If nesting is too deep.
*/
private void push(JSONObject jo) throws JSONException {
if (this.top >= maxdepth) {
throw new JSONException("Nesting too deep.");
}
this.stack[this.top] = jo;
this.mode = jo == null ? 'a' : 'k';
this.top += 1;
}
/** /**
* Make a JSON text of an Object value. If the object has an * Make a JSON text of an Object value. If the object has an
* value.toJSONString() method, then that method will be used to produce the * value.toJSONString() method, then that method will be used to produce the
@ -311,14 +113,12 @@ public class JSONWriter {
* <p> * <p>
* Warning: This method assumes that the data structure is acyclical. * Warning: This method assumes that the data structure is acyclical.
* *
* @param value * @param value The value to be serialized.
* The value to be serialized.
* @return a printable, displayable, transmittable representation of the * @return a printable, displayable, transmittable representation of the
* object, beginning with <code>{</code>&nbsp;<small>(left * object, beginning with <code>{</code>&nbsp;<small>(left
* brace)</small> and ending with <code>}</code>&nbsp;<small>(right * brace)</small> and ending with <code>}</code>&nbsp;<small>(right
* brace)</small>. * brace)</small>.
* @throws JSONException * @throws JSONException If the value is or contains an invalid number.
* If the value is or contains an invalid number.
*/ */
public static String valueToString(Object value) throws JSONException { public static String valueToString(Object value) throws JSONException {
if (value == null || value.equals(null)) { if (value == null || value.equals(null)) {
@ -339,7 +139,7 @@ public class JSONWriter {
if (value instanceof Number) { if (value instanceof Number) {
// not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex // not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
final String numberAsString = JSONObject.numberToString((Number) value); final String numberAsString = JSONObject.numberToString((Number) value);
if(JSONObject.NUMBER_PATTERN.matcher(numberAsString).matches()) { if (JSONObject.NUMBER_PATTERN.matcher(numberAsString).matches()) {
// Close enough to a JSON number that we will return it unquoted // Close enough to a JSON number that we will return it unquoted
return numberAsString; return numberAsString;
} }
@ -362,15 +162,217 @@ public class JSONWriter {
if (value.getClass().isArray()) { if (value.getClass().isArray()) {
return new JSONArray(value).toString(); return new JSONArray(value).toString();
} }
if(value instanceof Enum<?>){ if (value instanceof Enum<?>) {
return JSONObject.quote(((Enum<?>)value).name()); return JSONObject.quote(((Enum<?>) value).name());
} }
return JSONObject.quote(value.toString()); return JSONObject.quote(value.toString());
} }
/**
* Append a value.
*
* @param string A string value.
* @return this
* @throws JSONException If the value is out of sequence.
*/
private JSONWriter append(String string) throws JSONException {
if (string == null) {
throw new JSONException("Null pointer");
}
if (this.mode == 'o' || this.mode == 'a') {
try {
if (this.comma && this.mode == 'a') {
this.writer.append(',');
}
this.writer.append(string);
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
if (this.mode == 'o') {
this.mode = 'k';
}
this.comma = true;
return this;
}
throw new JSONException("Value out of sequence.");
}
/**
* Begin appending a new array. All values until the balancing
* <code>endArray</code> will be appended to this array. The
* <code>endArray</code> method must be called to mark the array's end.
*
* @return this
* @throws JSONException If the nesting is too deep, or if the object is
* started in the wrong place (for example as a key or after the end of the
* outermost array or object).
*/
public JSONWriter array() throws JSONException {
if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') {
this.push(null);
this.append("[");
this.comma = false;
return this;
}
throw new JSONException("Misplaced array.");
}
/**
* End something.
*
* @param m Mode
* @param c Closing character
* @return this
* @throws JSONException If unbalanced.
*/
private JSONWriter end(char m, char c) throws JSONException {
if (this.mode != m) {
throw new JSONException(m == 'a'
? "Misplaced endArray."
: "Misplaced endObject.");
}
this.pop(m);
try {
this.writer.append(c);
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
this.comma = true;
return this;
}
/**
* End an array. This method most be called to balance calls to
* <code>array</code>.
*
* @return this
* @throws JSONException If incorrectly nested.
*/
public JSONWriter endArray() throws JSONException {
return this.end('a', ']');
}
/**
* End an object. This method most be called to balance calls to
* <code>object</code>.
*
* @return this
* @throws JSONException If incorrectly nested.
*/
public JSONWriter endObject() throws JSONException {
return this.end('k', '}');
}
/**
* Append a key. The key will be associated with the next value. In an
* object, every value must be preceded by a key.
*
* @param string A key string.
* @return this
* @throws JSONException If the key is out of place. For example, keys
* do not belong in arrays or if the key is null.
*/
public JSONWriter key(String string) throws JSONException {
if (string == null) {
throw new JSONException("Null key.");
}
if (this.mode == 'k') {
try {
JSONObject topObject = this.stack[this.top - 1];
// don't use the built in putOnce method to maintain Android support
if (topObject.has(string)) {
throw new JSONException("Duplicate key \"" + string + "\"");
}
topObject.put(string, true);
if (this.comma) {
this.writer.append(',');
}
this.writer.append(JSONObject.quote(string));
this.writer.append(':');
this.comma = false;
this.mode = 'o';
return this;
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
}
throw new JSONException("Misplaced key.");
}
/**
* Begin appending a new object. All keys and values until the balancing
* <code>endObject</code> will be appended to this object. The
* <code>endObject</code> method must be called to mark the object's end.
*
* @return this
* @throws JSONException If the nesting is too deep, or if the object is
* started in the wrong place (for example as a key or after the end of the
* outermost array or object).
*/
public JSONWriter object() throws JSONException {
if (this.mode == 'i') {
this.mode = 'o';
}
if (this.mode == 'o' || this.mode == 'a') {
this.append("{");
this.push(new JSONObject());
this.comma = false;
return this;
}
throw new JSONException("Misplaced object.");
}
/**
* Pop an array or object scope.
*
* @param c The scope to close.
* @throws JSONException If nesting is wrong.
*/
private void pop(char c) throws JSONException {
if (this.top <= 0) {
throw new JSONException("Nesting error.");
}
char m = this.stack[this.top - 1] == null ? 'a' : 'k';
if (m != c) {
throw new JSONException("Nesting error.");
}
this.top -= 1;
this.mode = this.top == 0
? 'd'
: this.stack[this.top - 1] == null
? 'a'
: 'k';
}
/**
* Push an array or object scope.
*
* @param jo The scope to open.
* @throws JSONException If nesting is too deep.
*/
private void push(JSONObject jo) throws JSONException {
if (this.top >= maxdepth) {
throw new JSONException("Nesting too deep.");
}
this.stack[this.top] = jo;
this.mode = jo == null ? 'a' : 'k';
this.top += 1;
}
/** /**
* Append either the value <code>true</code> or the value * Append either the value <code>true</code> or the value
* <code>false</code>. * <code>false</code>.
*
* @param b A boolean. * @param b A boolean.
* @return this * @return this
* @throws JSONException * @throws JSONException
@ -381,6 +383,7 @@ public class JSONWriter {
/** /**
* Append a double value. * Append a double value.
*
* @param d A double. * @param d A double.
* @return this * @return this
* @throws JSONException If the number is not finite. * @throws JSONException If the number is not finite.
@ -391,6 +394,7 @@ public class JSONWriter {
/** /**
* Append a long value. * Append a long value.
*
* @param l A long. * @param l A long.
* @return this * @return this
* @throws JSONException * @throws JSONException
@ -402,8 +406,9 @@ public class JSONWriter {
/** /**
* Append an object value. * Append an object value.
*
* @param object The object to append. It can be null, or a Boolean, Number, * @param object The object to append. It can be null, or a Boolean, Number,
* String, JSONObject, or JSONArray, or an object that implements JSONString. * String, JSONObject, or JSONArray, or an object that implements JSONString.
* @return this * @return this
* @throws JSONException If the value is out of sequence. * @throws JSONException If the value is out of sequence.
*/ */

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.