Commit fe4e5990 authored by Melledy's avatar Melledy
Browse files

Merge branch 'development' into dev-world-scripts

parents 3cffdd97 e3ed3968
......@@ -25,6 +25,16 @@ jobs:
with:
distribution: temurin
java-version: '17'
- name: Cache gradle files
uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
./.gradle/loom-cache
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle', 'gradle.properties', '**/*.accesswidener') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Run Gradle
run: ./gradlew && ./gradlew jar
- name: Upload build
......
......@@ -17,7 +17,7 @@
*.nar
*.ear
*.zip
*.tar.gz
*.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
......@@ -52,21 +52,23 @@ tmp/
.vscode
# Grasscutter
resources/
logs/
plugins/
data/AbilityEmbryos.json
data/OpenConfig.json
/resources
/logs
/plugins
/data
/keys
/language
/languages
/src/generated
/*.jar
/*.sh
GM Handbook.txt
config.json
mitmdump.exe
*.jar
!lib/*.jar
mongod.exe
/src/generated/
/*.sh
language/
languages/
gacha-mapping.js
mappings.js
BuildConfig.java
......
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400&display=swap">
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
<style>
body {
background-color: #f0f0f0;
}
p {
font-weight: 300;
}
a, a:hover {
text-decoration: none !important;
color: #626976;
}
.content {
padding: 3rem 0;
}
.container {
color: #626976;
position: relative;
}
h2 {
font-size: 20px;
}
h3 {
font-size: 16px;
}
table {
border-collapse: collapse;
width: 70%;
margin: 0 auto;
}
table thead tr {
height: 60px;
background: #626976;
}
table thead tr th {
font-size: 18px;
color: white;
}
table tbody tr {
height: 50px;
background-color: #f5f5f5;
}
tbody tr:nth-child(even) {
background-color: #fdfdfd;
}
table th, table td {
text-align: left;
padding: 0 8px;
}
</style>
<title>GM Handbook</title>
</head>
<body>
<div class="content">
<div class="container">
<h2 class="mb-5">{{TITLE}}</h2>
<h3>{{TITLE_COMMANDS}}</h3>
<hr/>
<table>
<thead>
<tr>
<th>{{HEADER_COMMAND}}</th>
<th>{{HEADER_DESCRIPTION}}</th>
</tr>
</thead>
{{COMMANDS_TABLE}}
</table>
<h3>{{TITLE_AVATARS}}</h3>
<hr/>
<table>
<thead>
<tr>
<th>{{HEADER_ID}}</th>
<th>{{HEADER_AVATAR}}</th>
</tr>
</thead>
{{AVATARS_TABLE}}
</table>
<h3>{{TITLE_ITEMS}}</h3>
<hr/>
<table>
<thead>
<tr>
<th>{{HEADER_ID}}</th>
<th>{{HEADER_ITEM}}</th>
</tr>
</thead>
{{ITEMS_TABLE}}
</table>
<h3>{{TITLE_SCENES}}</h3>
<hr/>
<table>
<thead>
<tr>
<th>{{HEADER_ID}}</th>
<th>{{HEADER_SCENE}}</th>
</tr>
</thead>
{{SCENES_TABLE}}
</table>
<h3>{{TITLE_MONSTERS}}</h3>
<hr/>
<table>
<thead>
<tr>
<th>{{HEADER_ID}}</th>
<th>{{HEADER_MONSTER}}</th>
</tr>
</thead>
{{MONSTERS_TABLE}}
</table>
</div>
</div>
<footer>
<div class="copyright">
<div class="container">
<div class="row">
<div class="col-md-6">
<span>Template by BecodReyes. All rights reserved.</span>
</div>
<div class="col-md-6">
<ul style="float:right">
<li class="list-inline-item">
<a href="https://github.com/Grasscutters/Grasscutter">Github</a>
</li>
<li class="list-inline-item">·</li>
<li class="list-inline-item">
<a href="https://github.com/Grasscutters/Grasscutter/blob/stable/LICENSE">License</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</footer>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400&display=swap">
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css">
<style>
body {
background-color: #f0f0f0;
}
p {
font-weight: 300;
}
a, a:hover {
text-decoration: none !important;
color: #626976;
}
.content {
padding: 3rem 0;
}
.container {
color: #626976;
position: relative;
}
h2 {
font-size: 20px;
}
h3 {
font-size: 16px;
}
table {
border-collapse: collapse;
width: 70%;
margin: 0 auto;
}
table thead tr {
height: 60px;
background: #626976;
}
table thead tr th {
font-size: 18px;
color: white;
}
table tbody tr {
height: 50px;
background-color: #f5f5f5;
}
tbody tr:nth-child(even) {
background-color: #fdfdfd;
}
table th, table td {
text-align: left;
padding: 0 8px;
}
</style>
<title>Documentation</title>
</head>
<body>
<div class="content">
<div class="container">
<h2 class="mb-5">{{TITLE}}</h2>
<ul>
<li><a href="/documentation/handbook">{{ITEM_HANDBOOK}}</a></li>
<li><a href="/documentation/gachamapping">{{ITEM_GACHA_MAPPING}}</a></li>
</ul>
</div>
</div>
<footer>
<div class="copyright">
<div class="container">
<div class="row">
<div class="col-md-6">
<span>Template by BecodReyes. All rights reserved.</span>
</div>
<div class="col-md-6">
<ul style="float:right">
<li class="list-inline-item">
<a href="https://github.com/Grasscutters/Grasscutter">Github</a>
</li>
<li class="list-inline-item">·</li>
<li class="list-inline-item">
<a href="https://github.com/Grasscutters/Grasscutter/blob/stable/LICENSE">License</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</footer>
</body>
</html>
......@@ -28,7 +28,6 @@ public final class Configuration extends ConfigContainer {
public static final Locale FALLBACK_LANGUAGE = config.language.fallback;
private static final String DATA_FOLDER = config.folderStructure.data;
private static final String RESOURCES_FOLDER = config.folderStructure.resources;
private static final String KEYS_FOLDER = config.folderStructure.keys;
private static final String PLUGINS_FOLDER = config.folderStructure.plugins;
private static final String SCRIPTS_FOLDER = config.folderStructure.scripts;
private static final String PACKETS_FOLDER = config.folderStructure.packets;
......@@ -62,10 +61,6 @@ public final class Configuration extends ConfigContainer {
public static String RESOURCE(String path) {
return Paths.get(RESOURCES_FOLDER, path).toString();
}
public static String KEY(String path) {
return Paths.get(KEYS_FOLDER, path).toString();
}
public static String PLUGIN() {
return PLUGINS_FOLDER;
......
......@@ -14,6 +14,7 @@ import emu.grasscutter.server.http.HttpServer;
import emu.grasscutter.server.http.dispatch.DispatchHandler;
import emu.grasscutter.server.http.handlers.*;
import emu.grasscutter.server.http.dispatch.RegionHandler;
import emu.grasscutter.server.http.documentation.DocumentationServerHandler;
import emu.grasscutter.utils.ConfigContainer;
import emu.grasscutter.utils.Utils;
import org.jline.reader.EndOfFileException;
......@@ -129,6 +130,7 @@ public final class Grasscutter {
httpServer.addRouter(AnnouncementsHandler.class);
httpServer.addRouter(DispatchHandler.class);
httpServer.addRouter(GachaHandler.class);
httpServer.addRouter(DocumentationServerHandler.class);
// TODO: find a better place?
StaminaManager.initialize();
......
package emu.grasscutter.auth;
import emu.grasscutter.game.Account;
import emu.grasscutter.server.http.objects.*;
import express.http.Request;
import express.http.Response;
......@@ -30,10 +31,10 @@ public interface AuthenticationSystem {
/**
* Called by plugins to internally verify a user's identity.
* @param details A unique, one-time token to verify the user.
* @return True if the user is verified, False otherwise.
* @param details A unique identifier to identify the user. (For example: a JWT token)
* @return The user's account if the verification was successful, null if the user was unable to be verified.
*/
boolean verifyUser(String details);
Account verifyUser(String details);
/**
* This is the authenticator used for password authentication.
......@@ -59,6 +60,12 @@ public interface AuthenticationSystem {
*/
ExternalAuthenticator getExternalAuthenticator();
/**
* This is the authenticator used for handling OAuth authentication requests.
* @return An authenticator.
*/
OAuthAuthenticator getOAuthAuthenticator();
/**
* A data container that holds relevant data for authenticating a client.
*/
......@@ -124,4 +131,16 @@ public interface AuthenticationSystem {
return AuthenticationRequest.builder().request(request)
.response(response).build();
}
/**
* Generates an authentication request from a {@link Response} object.
* @param request The Express request.
* @param jsonData The JSON data.
* @return An authentication request.
*/
static AuthenticationRequest fromOAuthRequest(Request request, Response response) {
return AuthenticationRequest.builder().request(request)
.response(response).build();
}
}
......@@ -2,6 +2,7 @@ package emu.grasscutter.auth;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.auth.DefaultAuthenticators.*;
import emu.grasscutter.game.Account;
import emu.grasscutter.server.http.objects.ComboTokenResJson;
import emu.grasscutter.server.http.objects.LoginResultJson;
......@@ -16,6 +17,7 @@ public final class DefaultAuthentication implements AuthenticationSystem {
private final Authenticator<LoginResultJson> tokenAuthenticator = new TokenAuthenticator();
private final Authenticator<ComboTokenResJson> sessionKeyAuthenticator = new SessionKeyAuthenticator();
private final ExternalAuthenticator externalAuthenticator = new ExternalAuthentication();
private final OAuthAuthenticator oAuthAuthenticator = new OAuthAuthentication();
@Override
public void createAccount(String username, String password) {
......@@ -26,11 +28,11 @@ public final class DefaultAuthentication implements AuthenticationSystem {
public void resetPassword(String username) {
// Unhandled. The default authenticator doesn't store passwords.
}
@Override
public boolean verifyUser(String details) {
public Account verifyUser(String details) {
Grasscutter.getLogger().info(translate("dispatch.authentication.default_unable_to_verify"));
return false;
return null;
}
@Override
......@@ -52,4 +54,9 @@ public final class DefaultAuthentication implements AuthenticationSystem {
public ExternalAuthenticator getExternalAuthenticator() {
return this.externalAuthenticator;
}
@Override
public OAuthAuthenticator getOAuthAuthenticator() {
return this.oAuthAuthenticator;
}
}
......@@ -41,10 +41,6 @@ public final class DefaultAuthenticators {
responseMessage = translate("messages.dispatch.account.username_create_error");
Grasscutter.getLogger().info(translate("messages.dispatch.account.account_login_create_error", address));
} else {
// Add default permissions.
for (var permission : ACCOUNT.defaultPermissions)
account.addPermission(permission);
// Continue with login.
successfulLogin = true;
......@@ -178,4 +174,29 @@ public final class DefaultAuthenticators {
request.getResponse().send("Authentication is not available with the default authentication method.");
}
}
/**
* Handles authentication requests from OAuth sources.
*/
public static class OAuthAuthentication implements OAuthAuthenticator {
@Override public void handleLogin(AuthenticationRequest request) {
assert request.getResponse() != null;
request.getResponse().send("Authentication is not available with the default authentication method.");
}
@Override public void handleDesktopRedirection(AuthenticationRequest request) {
assert request.getResponse() != null;
request.getResponse().send("Authentication is not available with the default authentication method.");
}
@Override public void handleMobileRedirection(AuthenticationRequest request) {
assert request.getResponse() != null;
request.getResponse().send("Authentication is not available with the default authentication method.");
}
@Override public void handleTokenProcess(AuthenticationRequest request) {
assert request.getResponse() != null;
request.getResponse().send("Authentication is not available with the default authentication method.");
}
}
}
package emu.grasscutter.auth;
import emu.grasscutter.auth.AuthenticationSystem.AuthenticationRequest;
/**
* Handles authentication via OAuth routes.
*/
public interface OAuthAuthenticator {
/**
* Called when an OAuth login request is made.
* @param request The authentication request.
*/
void handleLogin(AuthenticationRequest request);
/**
* Called when an client requests to redirect to login page.
* @param request The authentication request.
*/
void handleDesktopRedirection(AuthenticationRequest request);
void handleMobileRedirection(AuthenticationRequest request);
/**
* Called when an OAuth login requests callback.
* @param request The authentication request.
*/
void handleTokenProcess(AuthenticationRequest request);
}
......@@ -2,6 +2,8 @@ package emu.grasscutter.command;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.server.event.game.CommandResponseEvent;
import emu.grasscutter.server.event.types.ServerEvent;
import java.util.List;
......@@ -19,6 +21,8 @@ public interface CommandHandler {
} else {
player.dropMessage(message);
}
CommandResponseEvent event = new CommandResponseEvent(ServerEvent.Type.GAME,player, message);
event.call();
}
/**
......
......@@ -9,7 +9,7 @@ import java.util.List;
import static emu.grasscutter.utils.Language.translate;
@Command(label = "resetshop", usage = "resetshop", permission = "server.resetshop", permissionTargeted = "server.resetshop.others", description = "commands.resetshop.description")
@Command(label = "resetshop", usage = "resetshop <player id>", permission = "server.resetshop", permissionTargeted = "server.resetshop.others", description = "commands.resetShopLimit.description")
public final class ResetShopLimitCommand implements CommandHandler {
@Override
......@@ -19,6 +19,11 @@ public final class ResetShopLimitCommand implements CommandHandler {
return;
}
if (args.isEmpty()) {
CommandHandler.sendMessage(sender, translate(sender, "commands.resetShopLimit.usage"));
return;
}
targetPlayer.getShopLimit().forEach(x -> x.setNextRefreshTime(0));
targetPlayer.save();
CommandHandler.sendMessage(sender, translate(sender, "commands.status.success"));
......
package emu.grasscutter.data;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.server.http.handlers.GachaHandler;
import emu.grasscutter.tools.Tools;
import emu.grasscutter.utils.FileUtils;
import emu.grasscutter.utils.Utils;
import java.io.*;
import java.nio.file.Path;
import java.util.List;
import static emu.grasscutter.Configuration.DATA;
public class DataLoader {
/**
* Load a data file by its name. If the file isn't found within the /data directory then it will fallback to the default within the jar resources
* @see #load(String, boolean)
* @param resourcePath The path to the data file to be loaded.
* @return InputStream of the data file.
* @throws FileNotFoundException
*/
public static InputStream load(String resourcePath) throws FileNotFoundException {
return load(resourcePath, true);
}
/**
* Load a data file by its name.
* @param resourcePath The path to the data file to be loaded.
* @param useFallback If the file does not exist in the /data directory, should it use the default file in the jar?
* @return InputStream of the data file.
* @throws FileNotFoundException
*/
public static InputStream load(String resourcePath, boolean useFallback) throws FileNotFoundException {
if(Utils.fileExists(DATA(resourcePath))) {
// Data is in the resource directory
return new FileInputStream(DATA(resourcePath));
} else {
if(useFallback) {
return FileUtils.readResourceAsStream("/defaults/data/" + resourcePath);
}
}
return null;
}
public static void CheckAllFiles() {
try {
List<Path> filenames = FileUtils.getPathsFromResource("/defaults/data/");
for (Path file : filenames) {
String relativePath = String.valueOf(file).split("/defaults/data/")[1];
CheckAndCopyData(relativePath);
}
} catch (Exception e) {
Grasscutter.getLogger().error("An error occurred while trying to check the data folder. \n" + e);
}
GenerateGachaMappings();
}
private static void CheckAndCopyData(String name) {
String filePath = Utils.toFilePath(DATA(name));
if (!Utils.fileExists(filePath)) {
// Check if file is in subdirectory
if (name.indexOf("/") != -1) {
String[] path = name.split("/");
String folder = "";
for(int i = 0; i < (path.length - 1); i++) {
folder += path[i] + "/";
// Make sure the current folder exists
String folderToCreate = Utils.toFilePath(DATA(folder));
if(!Utils.fileExists(folderToCreate)) {
Grasscutter.getLogger().info("Creating data folder '" + folder + "'");
Utils.createFolder(folderToCreate);
}
}
}
Grasscutter.getLogger().info("Creating default '" + name + "' data");
FileUtils.copyResource("/defaults/data/" + name, filePath);
}
}
private static void GenerateGachaMappings() {
if (!Utils.fileExists(GachaHandler.gachaMappings)) {
try {
Grasscutter.getLogger().info("Creating default '" + GachaHandler.gachaMappings + "' data");
Tools.createGachaMapping(GachaHandler.gachaMappings);
} catch (Exception exception) {
Grasscutter.getLogger().warn("Failed to create gacha mappings. \n" + exception);
}
}
}
}
package emu.grasscutter.data;
import java.io.File;
import java.io.FileReader;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.regex.Matcher;
......@@ -33,6 +32,8 @@ import static emu.grasscutter.Configuration.*;
public class ResourceLoader {
private static List<String> loadedResources = new ArrayList<String>();
public static List<Class<?>> getResourceDefClasses() {
Reflections reflections = new Reflections(ResourceLoader.class.getPackage().getName());
Set<?> classes = reflections.getSubTypesOf(GameResource.class);
......@@ -98,6 +99,10 @@ public class ResourceLoader {
}
public static void loadResources() {
loadResources(false);
}
public static void loadResources(boolean doReload) {
for (Class<?> resourceDefinition : getResourceDefClasses()) {
ResourceType type = resourceDefinition.getAnnotation(ResourceType.class);
......@@ -113,7 +118,7 @@ public class ResourceLoader {
}
try {
loadFromResource(resourceDefinition, type, map);
loadFromResource(resourceDefinition, type, map, doReload);
} catch (Exception e) {
Grasscutter.getLogger().error("Error loading resource file: " + Arrays.toString(type.name()), e);
}
......@@ -121,13 +126,16 @@ public class ResourceLoader {
}
@SuppressWarnings("rawtypes")
protected static void loadFromResource(Class<?> c, ResourceType type, Int2ObjectMap map) throws Exception {
for (String name : type.name()) {
loadFromResource(c, name, map);
protected static void loadFromResource(Class<?> c, ResourceType type, Int2ObjectMap map, boolean doReload) throws Exception {
if(!loadedResources.contains(c.getSimpleName()) || doReload) {
for (String name : type.name()) {
loadFromResource(c, name, map);
}
Grasscutter.getLogger().info("Loaded " + map.size() + " " + c.getSimpleName() + "s.");
loadedResources.add(c.getSimpleName());
}
Grasscutter.getLogger().info("Loaded " + map.size() + " " + c.getSimpleName() + "s.");
}
@SuppressWarnings({"rawtypes", "unchecked"})
protected static void loadFromResource(Class<?> c, String fileName, Int2ObjectMap map) throws Exception {
FileReader fileReader = new FileReader(RESOURCE("ExcelBinOutput/" + fileName));
......@@ -138,6 +146,9 @@ public class ResourceLoader {
Map<String, Object> tempMap = Utils.switchPropertiesUpperLowerCase((Map<String, Object>) o, c);
GameResource res = gson.fromJson(gson.toJson(tempMap), TypeToken.get(c).getType());
res.onLoad();
if(map.containsKey(res.getId())) {
map.remove(res.getId());
}
map.put(res.getId(), res);
}
}
......@@ -191,18 +202,14 @@ public class ResourceLoader {
}
private static void loadAbilityEmbryos() {
// Read from cached file if exists
File embryoCache = new File(DATA("AbilityEmbryos.json"));
List<AbilityEmbryoEntry> embryoList = null;
if (embryoCache.exists()) {
// Load from cache
try (FileReader fileReader = new FileReader(embryoCache)) {
embryoList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, AbilityEmbryoEntry.class).getType());
} catch (Exception e) {
e.printStackTrace();
}
} else {
// Read from cached file if exists
try(InputStream embryoCache = DataLoader.load("AbilityEmbryos.json", false)) {
embryoList = Grasscutter.getGsonFactory().fromJson(new InputStreamReader(embryoCache), TypeToken.getParameterized(Collection.class, AbilityEmbryoEntry.class).getType());
} catch(Exception ignored) {}
if(embryoList == null) {
// Load from BinOutput
Pattern pattern = Pattern.compile("(?<=ConfigAvatar_)(.*?)(?=.json)");
......@@ -316,18 +323,12 @@ public class ResourceLoader {
}
private static void loadSpawnData() {
// Read from cached file if exists
File spawnDataEntries = new File(DATA("Spawns.json"));
List<SpawnGroupEntry> spawnEntryList = null;
if (spawnDataEntries.exists()) {
// Load from cache
try (FileReader fileReader = new FileReader(spawnDataEntries)) {
spawnEntryList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, SpawnGroupEntry.class).getType());
} catch (Exception e) {
e.printStackTrace();
}
}
// Read from cached file if exists
try(InputStream spawnDataEntries = DataLoader.load("Spawns.json")) {
spawnEntryList = Grasscutter.getGsonFactory().fromJson(new InputStreamReader(spawnDataEntries), TypeToken.getParameterized(Collection.class, SpawnGroupEntry.class).getType());
} catch (Exception ignored) {}
if (spawnEntryList == null || spawnEntryList.isEmpty()) {
Grasscutter.getLogger().error("No spawn data loaded!");
......@@ -342,16 +343,13 @@ public class ResourceLoader {
private static void loadOpenConfig() {
// Read from cached file if exists
File openConfigCache = new File(DATA("OpenConfig.json"));
List<OpenConfigEntry> list = null;
if (openConfigCache.exists()) {
try (FileReader fileReader = new FileReader(openConfigCache)) {
list = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, OpenConfigEntry.class).getType());
} catch (Exception e) {
e.printStackTrace();
}
} else {
try(InputStream openConfigCache = DataLoader.load("OpenConfig.json", false)) {
list = Grasscutter.getGsonFactory().fromJson(new InputStreamReader(openConfigCache), TypeToken.getParameterized(Collection.class, SpawnGroupEntry.class).getType());
} catch (Exception ignored) {}
if (list == null) {
Map<String, OpenConfigEntry> map = new TreeMap<>();
java.lang.reflect.Type type = new TypeToken<Map<String, OpenConfigData[]>>() {}.getType();
String[] folderNames = {"BinOutput/Talent/EquipTalents/", "BinOutput/Talent/AvatarTalents/"};
......
package emu.grasscutter.game;
import dev.morphia.annotations.*;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.database.DatabaseHelper;
import emu.grasscutter.utils.Crypto;
import emu.grasscutter.utils.Utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.*;
import java.util.stream.Stream;
import org.bson.Document;
......@@ -144,19 +142,24 @@ public class Account {
}
public boolean hasPermission(String permission) {
if (this.permissions.contains(permission)) return true;
if(this.permissions.contains("*") && this.permissions.size() == 1) return true;
// Add default permissions if it doesn't exist
List<String> permissions = Stream.of(this.permissions, Arrays.asList(ACCOUNT.defaultPermissions))
.flatMap(Collection::stream)
.distinct().toList();
if (permissions.contains(permission)) return true;
String[] permissionParts = permission.split("\\.");
for (String p : this.permissions) {
for (String p : permissions) {
if (p.startsWith("-") && permissionMatchesWildcard(p.substring(1), permissionParts)) return false;
if (permissionMatchesWildcard(p, permissionParts)) return true;
}
return this.permissions.contains("*");
return permissions.contains("*");
}
public boolean removePermission(String permission) {
return this.permissions.remove(permission);
}
......
......@@ -2,6 +2,7 @@ package emu.grasscutter.game.drop;
import com.google.gson.reflect.TypeToken;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.DataLoader;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.game.entity.EntityItem;
......@@ -17,12 +18,11 @@ import emu.grasscutter.utils.Utils;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Collection;
import java.util.List;
import static emu.grasscutter.Configuration.*;
public class DropManager {
public GameServer getGameServer() {
return gameServer;
......@@ -43,7 +43,7 @@ public class DropManager {
}
public synchronized void load() {
try (FileReader fileReader = new FileReader(DATA("Drop.json"))) {
try (Reader fileReader = new InputStreamReader(DataLoader.load("Drop.json"))) {
getDropData().clear();
List<DropInfo> banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, DropInfo.class).getType());
if(banners.size() > 0) {
......
......@@ -2,11 +2,14 @@ package emu.grasscutter.game.expedition;
import com.google.gson.reflect.TypeToken;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.DataLoader;
import emu.grasscutter.server.game.GameServer;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Collection;
import java.util.List;
......@@ -30,7 +33,7 @@ public class ExpeditionManager {
}
public synchronized void load() {
try (FileReader fileReader = new FileReader(DATA("ExpeditionReward.json"))) {
try (Reader fileReader = new InputStreamReader(DataLoader.load("ExpeditionReward.json"))) {
getExpeditionRewardDataList().clear();
List<ExpeditionRewardInfo> banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ExpeditionRewardInfo.class).getType());
if(banners.size() > 0) {
......
......@@ -2,6 +2,8 @@ package emu.grasscutter.game.gacha;
import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.Arrays;
......@@ -13,6 +15,7 @@ import com.google.gson.reflect.TypeToken;
import com.sun.nio.file.SensitivityWatchEventModifier;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.DataLoader;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.common.ItemParamData;
import emu.grasscutter.data.def.ItemData;
......@@ -74,7 +77,7 @@ public class GachaManager {
}
public synchronized void load() {
try (FileReader fileReader = new FileReader(DATA("Banners.json"))) {
try (Reader fileReader = new InputStreamReader(DataLoader.load("Banners.json"))) {
getGachaBanners().clear();
List<GachaBanner> banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, GachaBanner.class).getType());
if(banners.size() > 0) {
......
......@@ -2,6 +2,7 @@ package emu.grasscutter.game.shop;
import com.google.gson.reflect.TypeToken;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.DataLoader;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.common.ItemParamData;
import emu.grasscutter.data.def.ShopGoodsData;
......@@ -11,6 +12,8 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
......@@ -58,7 +61,7 @@ public class ShopManager {
}
private void loadShop() {
try (FileReader fileReader = new FileReader(DATA("Shop.json"))) {
try (Reader fileReader = new InputStreamReader(DataLoader.load("Shop.json"))) {
getShopData().clear();
List<ShopTable> banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopTable.class).getType());
if(banners.size() > 0) {
......@@ -102,7 +105,7 @@ public class ShopManager {
}
private void loadShopChest() {
try (FileReader fileReader = new FileReader(DATA("ShopChest.json"))) {
try (Reader fileReader = new InputStreamReader(DataLoader.load("ShopChest.json"))) {
getShopChestData().clear();
List<ShopChestTable> shopChestTableList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopChestTable.class).getType());
if (shopChestTableList.size() > 0) {
......@@ -117,7 +120,7 @@ public class ShopManager {
}
private void loadShopChestBatchUse() {
try (FileReader fileReader = new FileReader(DATA("ShopChestBatchUse.json"))) {
try (Reader fileReader = new InputStreamReader(DataLoader.load("ShopChestBatchUse.json"))) {
getShopChestBatchUseData().clear();
List<ShopChestBatchUseTable> shopChestBatchUseTableList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopChestBatchUseTable.class).getType());
if (shopChestBatchUseTableList.size() > 0) {
......
package emu.grasscutter.game.tower;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.DataLoader;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.TowerScheduleData;
import emu.grasscutter.server.game.GameServer;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.List;
import static emu.grasscutter.Configuration.*;
......@@ -25,7 +28,7 @@ public class TowerScheduleManager {
private TowerScheduleConfig towerScheduleConfig;
public synchronized void load(){
try (FileReader fileReader = new FileReader(DATA("TowerSchedule.json"))) {
try (Reader fileReader = new InputStreamReader(DataLoader.load("TowerSchedule.json"))) {
towerScheduleConfig = Grasscutter.getGsonFactory().fromJson(fileReader, TowerScheduleConfig.class);
} catch (Exception e) {
Grasscutter.getLogger().error("Unable to load tower schedule config.", e);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment