semi-auto cleanup
This commit is contained in:
1 parent
cad80f82c6
commit
8f61271606
99 files changed
+11463
-8007
No files matched your search
@@ -18,6 +18,7 @@ import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.commands.CommandRuntimeException;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.world.level.storage.LevelResource;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -40,22 +41,28 @@ import org.apache.commons.io.IOUtils;
|
||||
*/
|
||||
public class AppStoreManager
|
||||
{
|
||||
/** A local copy of the scarpet repo's file structure, to avoid multiple queries to github.com while typing out the
|
||||
/**
|
||||
* A local copy of the scarpet repo's file structure, to avoid multiple queries to github.com while typing out the
|
||||
* {@code /script download} command and getting the suggestions.
|
||||
*/
|
||||
private static StoreNode APP_STORE_ROOT = StoreNode.folder(null, "");
|
||||
|
||||
/** This is the base link to the scarpet app repo from the github api.
|
||||
/**
|
||||
* This is the base link to the scarpet app repo from the github api.
|
||||
*/
|
||||
private static String scarpetRepoLink = "https://api.github.com/repos/gnembon/scarpet/contents/programs/";
|
||||
|
||||
private static record AppInfo(String name, String url, StoreNode source) {}
|
||||
private record AppInfo(String name, String url, StoreNode source)
|
||||
{
|
||||
}
|
||||
|
||||
public static class ScarpetAppStoreValidator extends Validator<String>
|
||||
{
|
||||
@Override public String validate(CommandSourceStack source, CarpetRule<String> currentRule, String newValue, String stringInput)
|
||||
@Override
|
||||
public String validate(final CommandSourceStack source, final CarpetRule<String> currentRule, String newValue, final String stringInput)
|
||||
{
|
||||
if (newValue.equals(currentRule.value())) {
|
||||
if (newValue.equals(currentRule.value()))
|
||||
{
|
||||
// Don't refresh the local repo if it's the same (world change), helps preventing hitting rate limits from github when
|
||||
// getting suggestions. Pending is a way to invalidate the cache when it gets old, and investigating api usage further
|
||||
return newValue;
|
||||
@@ -66,12 +73,19 @@ public class AppStoreManager
|
||||
scarpetRepoLink = null;
|
||||
return newValue;
|
||||
}
|
||||
if (newValue.endsWith("/")) newValue = newValue.replaceAll("/$", "");
|
||||
scarpetRepoLink = "https://api.github.com/repos/"+newValue+"/";
|
||||
if (newValue.endsWith("/"))
|
||||
{
|
||||
newValue = newValue.replaceAll("/$", "");
|
||||
}
|
||||
scarpetRepoLink = "https://api.github.com/repos/" + newValue + "/";
|
||||
return newValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() { return "Appstore link should point to a valid github repository";}
|
||||
public String description()
|
||||
{
|
||||
return "Appstore link should point to a valid github repository";
|
||||
}
|
||||
}
|
||||
|
||||
public static class StoreNode
|
||||
@@ -81,18 +95,19 @@ public class AppStoreManager
|
||||
public Map<String, StoreNode> children;
|
||||
public boolean sealed;
|
||||
public String value;
|
||||
public static StoreNode folder(StoreNode parent, String name)
|
||||
|
||||
public static StoreNode folder(final StoreNode parent, final String name)
|
||||
{
|
||||
StoreNode node = new StoreNode(parent, name);
|
||||
final StoreNode node = new StoreNode(parent, name);
|
||||
node.children = new HashMap<>();
|
||||
node.value = null;
|
||||
node.sealed = false;
|
||||
return node;
|
||||
}
|
||||
|
||||
public static StoreNode scriptFile(StoreNode parent, String name, String value)
|
||||
public static StoreNode scriptFile(final StoreNode parent, final String name, final String value)
|
||||
{
|
||||
StoreNode node = new StoreNode(parent, name);
|
||||
final StoreNode node = new StoreNode(parent, name);
|
||||
node.children = null;
|
||||
node.value = value;
|
||||
node.sealed = true;
|
||||
@@ -103,19 +118,23 @@ public class AppStoreManager
|
||||
{
|
||||
return value != null;
|
||||
}
|
||||
|
||||
public String pathElement()
|
||||
{
|
||||
return name+(isLeaf()?"":"/");
|
||||
return name + (isLeaf() ? "" : "/");
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return createPrePath().toString();
|
||||
}
|
||||
|
||||
private StringBuilder createPrePath()
|
||||
{
|
||||
return this == APP_STORE_ROOT ? new StringBuilder() : parent.createPrePath().append(pathElement());
|
||||
}
|
||||
private StoreNode(StoreNode parent, String name)
|
||||
|
||||
private StoreNode(final StoreNode parent, final String name)
|
||||
{
|
||||
this.parent = parent;
|
||||
this.name = name;
|
||||
@@ -124,32 +143,38 @@ public class AppStoreManager
|
||||
|
||||
public synchronized void fillChildren() throws IOException
|
||||
{
|
||||
if (sealed) return;
|
||||
if (scarpetRepoLink == null) throw new IOException("Accessing scarpet app repo is disabled");
|
||||
if (sealed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (scarpetRepoLink == null)
|
||||
{
|
||||
throw new IOException("Accessing scarpet app repo is disabled");
|
||||
}
|
||||
|
||||
String queryPath = scarpetRepoLink + getPath();
|
||||
String response;
|
||||
final String queryPath = scarpetRepoLink + getPath();
|
||||
final String response;
|
||||
try
|
||||
{
|
||||
response = IOUtils.toString(new URL(queryPath), StandardCharsets.UTF_8);
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
// Not sealing to allow retrying
|
||||
throw new IOException("Problems fetching " + queryPath, e);
|
||||
}
|
||||
JsonArray files = JsonParser.parseString(response).getAsJsonArray();
|
||||
for(JsonElement je : files)
|
||||
final JsonArray files = JsonParser.parseString(response).getAsJsonArray();
|
||||
for (final JsonElement je : files)
|
||||
{
|
||||
JsonObject jo = je.getAsJsonObject();
|
||||
String name = jo.get("name").getAsString();
|
||||
final JsonObject jo = je.getAsJsonObject();
|
||||
final String name = jo.get("name").getAsString();
|
||||
if (jo.get("type").getAsString().equals("dir"))
|
||||
{
|
||||
children.put(name, folder(this, name));
|
||||
}
|
||||
else// if (name.matches("(\\w+\\.scl?)"))
|
||||
{
|
||||
String value = jo.get("download_url").getAsString();
|
||||
final String value = jo.get("download_url").getAsString();
|
||||
children.put(name, scriptFile(this, name, value));
|
||||
}
|
||||
}
|
||||
@@ -159,12 +184,16 @@ public class AppStoreManager
|
||||
/**
|
||||
* Returns true if doing down the directory structire cannot continue since the matching element is either a leaf or
|
||||
* a string not matching of any node.
|
||||
*
|
||||
* @param pathElement
|
||||
* @return
|
||||
*/
|
||||
public boolean cannotContinueFor(String pathElement) throws IOException
|
||||
public boolean cannotContinueFor(final String pathElement) throws IOException
|
||||
{
|
||||
if (isLeaf()) return true;
|
||||
if (isLeaf())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
fillChildren();
|
||||
return !children.containsKey(pathElement);
|
||||
}
|
||||
@@ -173,120 +202,140 @@ public class AppStoreManager
|
||||
{
|
||||
if (isLeaf())
|
||||
{
|
||||
if (name.endsWith(".sc"))
|
||||
return Collections.singletonList(getPath());
|
||||
return Collections.emptyList();
|
||||
return name.endsWith(".sc") ? Collections.singletonList(getPath()) : Collections.emptyList();
|
||||
}
|
||||
fillChildren();
|
||||
String prefix = getPath();
|
||||
final String prefix = getPath();
|
||||
return children.values().stream().
|
||||
filter(n -> (!n.isLeaf() || n.name.endsWith(".sc"))).
|
||||
map(s -> prefix+s.pathElement().replaceAll("/$", "")).
|
||||
map(s -> prefix + s.pathElement().replaceAll("/$", "")).
|
||||
collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public StoreNode drillDown(String pathElement) throws IOException
|
||||
public StoreNode drillDown(final String pathElement) throws IOException
|
||||
{
|
||||
if (isLeaf()) throw new IOException(pathElement+" is not a folder");
|
||||
if (isLeaf())
|
||||
{
|
||||
throw new IOException(pathElement + " is not a folder");
|
||||
}
|
||||
fillChildren();
|
||||
if (!children.containsKey(pathElement)) throw new IOException("Folder "+pathElement+" is not present");
|
||||
if (!children.containsKey(pathElement))
|
||||
{
|
||||
throw new IOException("Folder " + pathElement + " is not present");
|
||||
}
|
||||
return children.get(pathElement);
|
||||
}
|
||||
|
||||
public String getValue(String file) throws IOException
|
||||
public String getValue(final String file) throws IOException
|
||||
{
|
||||
StoreNode leaf = drillDown(file);
|
||||
if (!leaf.isLeaf()) throw new IOException(file+" is not a file");
|
||||
final StoreNode leaf = drillDown(file);
|
||||
if (!leaf.isLeaf())
|
||||
{
|
||||
throw new IOException(file + " is not a file");
|
||||
}
|
||||
return leaf.value;
|
||||
}
|
||||
}
|
||||
|
||||
/** This method searches for valid file names from the user-inputted string, e.g if the user has thus far typed
|
||||
/**
|
||||
* This method searches for valid file names from the user-inputted string, e.g if the user has thus far typed
|
||||
* {@code survival/a} then it will return all the files in the {@code survival} directory of the scarpet repo (and
|
||||
* will automatically highlight those starting with a), and the string {@code survival/} as the current most valid path.
|
||||
*
|
||||
* @param currentPath The path down which we want to search for files
|
||||
* @return A pair of the current valid path, as well as the set of all the file/directory names at the end of that path
|
||||
*/
|
||||
public static List<String> suggestionsFromPath(String currentPath) throws IOException
|
||||
public static List<String> suggestionsFromPath(final String currentPath) throws IOException
|
||||
{
|
||||
String[] path = currentPath.split("/");
|
||||
final String[] path = currentPath.split("/");
|
||||
StoreNode appKiosk = APP_STORE_ROOT;
|
||||
for(String pathElement : path)
|
||||
for (final String pathElement : path)
|
||||
{
|
||||
if (appKiosk.cannotContinueFor(pathElement)) break;
|
||||
if (appKiosk.cannotContinueFor(pathElement))
|
||||
{
|
||||
break;
|
||||
}
|
||||
appKiosk = appKiosk.children.get(pathElement);
|
||||
}
|
||||
List<String> filteredSuggestions = appKiosk.createPathSuggestions().stream().filter(s -> s.startsWith(currentPath)).collect(Collectors.toList());
|
||||
if (filteredSuggestions.size() == 1) {
|
||||
final List<String> filteredSuggestions = appKiosk.createPathSuggestions().stream().filter(s -> s.startsWith(currentPath)).collect(Collectors.toList());
|
||||
if (filteredSuggestions.size() == 1)
|
||||
{
|
||||
if (!appKiosk.isLeaf())
|
||||
{
|
||||
return suggestionsFromPath(filteredSuggestions.get(0)); // Start suggesting directory contents
|
||||
}
|
||||
}
|
||||
return filteredSuggestions;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Downloads script and saves it to appropriate place.
|
||||
/**
|
||||
* Downloads script and saves it to appropriate place.
|
||||
*
|
||||
* @param path The user-inputted path to the script
|
||||
* @return {@code 1} if we succesfully saved the script, {@code 0} otherwise
|
||||
*/
|
||||
|
||||
public static int downloadScript(CommandSourceStack source, String path)
|
||||
public static int downloadScript(final CommandSourceStack source, final String path)
|
||||
{
|
||||
AppInfo nodeInfo = getFileNode(path);
|
||||
final AppInfo nodeInfo = getFileNode(path);
|
||||
return downloadScript(source, path, nodeInfo, false);
|
||||
}
|
||||
|
||||
private static int downloadScript(CommandSourceStack source, String path, AppInfo nodeInfo, boolean useTrash)
|
||||
private static int downloadScript(final CommandSourceStack source, final String path, final AppInfo nodeInfo, final boolean useTrash)
|
||||
{
|
||||
String code;
|
||||
final String code;
|
||||
try
|
||||
{
|
||||
code = IOUtils.toString(new URL(nodeInfo.url()), StandardCharsets.UTF_8);
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
throw new CommandRuntimeException(Messenger.c("rb Failed to obtain app file content: "+e.getMessage()));
|
||||
throw new CommandRuntimeException(Messenger.c("rb Failed to obtain app file content: " + e.getMessage()));
|
||||
}
|
||||
if (!saveScriptToFile(source, path, nodeInfo.name(), code, false, useTrash)) return 0;
|
||||
boolean success = CarpetServer.scriptServer.addScriptHost(source, nodeInfo.name().replaceFirst("\\.sc$", ""), null, true, false, false, nodeInfo.source());
|
||||
return success?1:0;
|
||||
if (!saveScriptToFile(source, path, nodeInfo.name(), code, false, useTrash))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
final boolean success = CarpetServer.scriptServer.addScriptHost(source, nodeInfo.name().replaceFirst("\\.sc$", ""), null, true, false, false, nodeInfo.source());
|
||||
return success ? 1 : 0;
|
||||
}
|
||||
|
||||
/** Gets the code once the user inputs the command.
|
||||
/**
|
||||
* Gets the code once the user inputs the command.
|
||||
*
|
||||
* @param appPath The user inputted path to the scarpet script
|
||||
* @return Pair of app file name and content
|
||||
*/
|
||||
public static AppInfo getFileNode(String appPath)
|
||||
public static AppInfo getFileNode(final String appPath)
|
||||
{
|
||||
return getFileNodeFrom(APP_STORE_ROOT, appPath);
|
||||
}
|
||||
|
||||
public static AppInfo getFileNodeFrom(StoreNode start, String appPath)
|
||||
public static AppInfo getFileNodeFrom(final StoreNode start, final String appPath)
|
||||
{
|
||||
String[] path = appPath.split("/");
|
||||
final String[] path = appPath.split("/");
|
||||
StoreNode appKiosk = start;
|
||||
try
|
||||
{
|
||||
for(String pathElement : Arrays.copyOfRange(path, 0, path.length-1))
|
||||
for (final String pathElement : Arrays.copyOfRange(path, 0, path.length - 1))
|
||||
{
|
||||
appKiosk = appKiosk.drillDown(pathElement);
|
||||
String appName = path[path.length-1];
|
||||
}
|
||||
final String appName = path[path.length - 1];
|
||||
appKiosk.getValue(appName);
|
||||
return new AppInfo(appName, appKiosk.getValue(appName), appKiosk);
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
throw new CommandRuntimeException(Messenger.c("rb '"+ appPath + "' is not a valid path to a scarpet app: "+e.getMessage()));
|
||||
throw new CommandRuntimeException(Messenger.c("rb '" + appPath + "' is not a valid path to a scarpet app: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean saveScriptToFile(CommandSourceStack source, String path, String appFileName, String code, boolean globalSavePath, boolean useTrash)
|
||||
public static boolean saveScriptToFile(final CommandSourceStack source, final String path, final String appFileName, final String code, final boolean globalSavePath, final boolean useTrash)
|
||||
{
|
||||
Path scriptLocation;
|
||||
final Path scriptLocation;
|
||||
if (globalSavePath && !source.getServer().isDedicatedServer()) // never happens, this is always called with globalSavePath being false
|
||||
{ //cos config folder only is in clients
|
||||
scriptLocation = FabricLoader.getInstance().getConfigDir().resolve("carpet/scripts/appstore").toAbsolutePath().resolve(path);
|
||||
@@ -307,29 +356,29 @@ public class AppStoreManager
|
||||
int i = 0;
|
||||
while (Files.exists(trashPath))
|
||||
{
|
||||
String[] nameAndExtension = appFileName.split("\\.");
|
||||
String newFileName = String.format(nameAndExtension[0] + "%02d." + nameAndExtension[1],i);
|
||||
final String[] nameAndExtension = appFileName.split("\\.");
|
||||
final String newFileName = String.format(nameAndExtension[0] + "%02d." + nameAndExtension[1], i);
|
||||
trashPath = trashPath.getParent().resolve(newFileName);
|
||||
i++;
|
||||
}
|
||||
Files.move(scriptLocation, trashPath);
|
||||
}
|
||||
Messenger.m(source, String.format("gi Note: replaced existing app '%s'"+(useTrash ? " (old moved to /trash folder)" : ""), appFileName));
|
||||
Messenger.m(source, String.format("gi Note: replaced existing app '%s'" + (useTrash ? " (old moved to /trash folder)" : ""), appFileName));
|
||||
}
|
||||
BufferedWriter writer = Files.newBufferedWriter(scriptLocation);
|
||||
final BufferedWriter writer = Files.newBufferedWriter(scriptLocation);
|
||||
writer.write(code);
|
||||
writer.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
Messenger.m(source, "r Error while downloading app: " + e.toString());
|
||||
Messenger.m(source, "r Error while downloading app: " + e);
|
||||
CarpetScriptServer.LOG.warn("Error while downloading app", e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void writeUrlToFile(String url, Path destination) throws IOException
|
||||
public static void writeUrlToFile(final String url, final Path destination) throws IOException
|
||||
{
|
||||
try (final InputStream in = new URL(url).openStream())
|
||||
{
|
||||
@@ -337,88 +386,112 @@ public class AppStoreManager
|
||||
}
|
||||
}
|
||||
|
||||
private static String getFullContentUrl(String original, StoreNode storeSource)
|
||||
private static String getFullContentUrl(final String original, final StoreNode storeSource)
|
||||
{
|
||||
if (original.matches("^https?://.*$")) // We've got a full url here: Just use it
|
||||
{
|
||||
return original;
|
||||
}
|
||||
if (original.charAt(0) == '/') // We've got an absolute path: Use app store root
|
||||
{
|
||||
return getFileNode(original.substring(1)).url();
|
||||
}
|
||||
return getFileNodeFrom(storeSource, original).url(); // Relative path: Use download location
|
||||
}
|
||||
|
||||
public static void addResource(CarpetScriptHost carpetScriptHost, StoreNode storeSource, Value resource)
|
||||
public static void addResource(final CarpetScriptHost carpetScriptHost, final StoreNode storeSource, final Value resource)
|
||||
{
|
||||
if (!(resource instanceof MapValue))
|
||||
throw new InternalExpressionException("This is not a valid resource map: "+resource.getString());
|
||||
Map<String, Value> resourceMap = ((MapValue) resource).getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), Map.Entry::getValue));
|
||||
if (!resourceMap.containsKey("source")) throw new InternalExpressionException("Missing 'source' field in resource descriptor: "+resource.getString());
|
||||
String source = resourceMap.get("source").getString();
|
||||
String contentUrl = getFullContentUrl(source, storeSource);
|
||||
String target = resourceMap.computeIfAbsent("target", k -> new StringValue(contentUrl.substring(contentUrl.lastIndexOf('/') + 1))).getString();
|
||||
boolean shared = resourceMap.getOrDefault("shared", Value.FALSE).getBoolean();
|
||||
if (!(resource instanceof final MapValue map))
|
||||
{
|
||||
throw new InternalExpressionException("This is not a valid resource map: " + resource.getString());
|
||||
}
|
||||
final Map<String, Value> resourceMap = map.getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), Map.Entry::getValue));
|
||||
if (!resourceMap.containsKey("source"))
|
||||
{
|
||||
throw new InternalExpressionException("Missing 'source' field in resource descriptor: " + resource.getString());
|
||||
}
|
||||
final String source = resourceMap.get("source").getString();
|
||||
final String contentUrl = getFullContentUrl(source, storeSource);
|
||||
final String target = resourceMap.computeIfAbsent("target", k -> new StringValue(contentUrl.substring(contentUrl.lastIndexOf('/') + 1))).getString();
|
||||
final boolean shared = resourceMap.getOrDefault("shared", Value.FALSE).getBoolean();
|
||||
|
||||
if (!carpetScriptHost.applyActionForResource(target, shared, p -> {
|
||||
try {
|
||||
try
|
||||
{
|
||||
writeUrlToFile(contentUrl, p);
|
||||
} catch (IOException e) {
|
||||
throw new InternalExpressionException("Unable to write resource "+target+": "+e.toString());
|
||||
}
|
||||
catch (final IOException e)
|
||||
{
|
||||
throw new InternalExpressionException("Unable to write resource " + target + ": " + e);
|
||||
}
|
||||
}))
|
||||
{
|
||||
throw new InternalExpressionException("Unable to write resource "+target);
|
||||
throw new InternalExpressionException("Unable to write resource " + target);
|
||||
}
|
||||
CarpetScriptServer.LOG.info("Downloaded resource "+target+" from "+contentUrl);
|
||||
CarpetScriptServer.LOG.info("Downloaded resource " + target + " from " + contentUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a new StoreNode for an app's dependency with proper relativeness. Will be null if it comes from an external URL
|
||||
*
|
||||
* @param originalSource The StoreNode from the container's app
|
||||
* @param sourceString The string the app specified as source
|
||||
* @param contentUrl The full content URL, from {@link #getFullContentUrl(String, StoreNode)}
|
||||
* @param sourceString The string the app specified as source
|
||||
* @param contentUrl The full content URL, from {@link #getFullContentUrl(String, StoreNode)}
|
||||
* @return A {@link StoreNode} that can be used in an app that came from the provided source
|
||||
*/
|
||||
private static StoreNode getNewStoreNode(StoreNode originalSource, String sourceString, String contentUrl)
|
||||
private static StoreNode getNewStoreNode(final StoreNode originalSource, String sourceString, final String contentUrl)
|
||||
{
|
||||
StoreNode next = originalSource;
|
||||
if (sourceString == contentUrl) // External URL (check getFullUrlContent)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (sourceString.charAt(0) == '/') // Absolute URL
|
||||
{
|
||||
next = APP_STORE_ROOT;
|
||||
sourceString = sourceString.substring(1);
|
||||
}
|
||||
String[] dirs = sourceString.split("/");
|
||||
final String[] dirs = sourceString.split("/");
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < dirs.length - 1; i++)
|
||||
{
|
||||
next = next.drillDown(dirs[i]);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
return null; // Should never happen, but let's not give a potentially incorrect node just in case
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
public static void addLibrary(CarpetScriptHost carpetScriptHost, StoreNode storeSource, Value library) {
|
||||
if (!(library instanceof MapValue))
|
||||
throw new InternalExpressionException("This is not a valid library map: "+library.getString());
|
||||
Map<String, String> libraryMap = ((MapValue) library).getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), e -> e.getValue().getString()));
|
||||
String source = libraryMap.get("source");
|
||||
String contentUrl = getFullContentUrl(source, storeSource);
|
||||
String target = libraryMap.computeIfAbsent("target", k -> contentUrl.substring(contentUrl.lastIndexOf('/') + 1));
|
||||
public static void addLibrary(final CarpetScriptHost carpetScriptHost, final StoreNode storeSource, final Value library)
|
||||
{
|
||||
if (!(library instanceof final MapValue map))
|
||||
{
|
||||
throw new InternalExpressionException("This is not a valid library map: " + library.getString());
|
||||
}
|
||||
final Map<String, String> libraryMap = map.getMap().entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getString(), e -> e.getValue().getString()));
|
||||
final String source = libraryMap.get("source");
|
||||
final String contentUrl = getFullContentUrl(source, storeSource);
|
||||
final String target = libraryMap.computeIfAbsent("target", k -> contentUrl.substring(contentUrl.lastIndexOf('/') + 1));
|
||||
if (!(contentUrl.endsWith(".sc") || contentUrl.endsWith(".scl")))
|
||||
{
|
||||
throw new InternalExpressionException("App resource type must download a scarpet app or library.");
|
||||
}
|
||||
if (target.indexOf('/') != -1)
|
||||
{
|
||||
throw new InternalExpressionException("App resource tried to leave script reserved space");
|
||||
}
|
||||
try
|
||||
{
|
||||
downloadScript(carpetScriptHost.responsibleSource, target, new AppInfo(target, contentUrl, getNewStoreNode(storeSource, source, contentUrl)), true);
|
||||
}
|
||||
catch (CommandRuntimeException e)
|
||||
catch (final CommandRuntimeException e)
|
||||
{
|
||||
throw new InternalExpressionException("Error when installing app dependencies: " + e.toString());
|
||||
throw new InternalExpressionException("Error when installing app dependencies: " + e);
|
||||
}
|
||||
CarpetScriptServer.LOG.info("Downloaded app "+target+" from "+contentUrl);
|
||||
CarpetScriptServer.LOG.info("Downloaded app " + target + " from " + contentUrl);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.StringValue;
|
||||
import carpet.script.value.Value;
|
||||
import carpet.script.value.ValueConversions;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -20,12 +21,9 @@ import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
|
||||
public class BiomeInfo
|
||||
{
|
||||
public final static Map<String, BiFunction<ServerLevel, Biome, Value>> biomeFeatures = new HashMap<String, BiFunction<ServerLevel, Biome, Value>>(){{
|
||||
//put("top_material", (w, b) -> new BlockValue( b.getGenerationSettings(). getSurfaceConfig().getTopMaterial(), null, null));
|
||||
//put("under_material", (w, b) -> new BlockValue( b.getGenerationSettings().getSurfaceConfig().getUnderMaterial(), null, null));
|
||||
//put("category", (w, b) -> StringValue.of(Biome.getBiomeCategory(Holder.direct(b)).getName()));
|
||||
public static final Map<String, BiFunction<ServerLevel, Biome, Value>> biomeFeatures = new HashMap<>()
|
||||
{{
|
||||
put("tags", (w, b) -> ListValue.wrap(w.registryAccess().registryOrThrow(Registries.BIOME).getTags().filter(p -> p.getSecond().stream().anyMatch(h -> h.value() == b)).map(p -> p.getFirst().location()).map(ValueConversions::of)));
|
||||
|
||||
put("temperature", (w, b) -> NumericValue.of(b.getBaseTemperature()));
|
||||
put("fog_color", (w, b) -> ValueConversions.ofRGB(b.getSpecialEffects().getFogColor()));
|
||||
put("foliage_color", (w, b) -> ValueConversions.ofRGB(b.getSpecialEffects().getFoliageColorOverride().orElse(4764952))); // client Biome.getDefaultFoliageColor
|
||||
@@ -34,11 +32,8 @@ public class BiomeInfo
|
||||
put("water_fog_color", (w, b) -> ValueConversions.ofRGB(b.getSpecialEffects().getWaterFogColor()));
|
||||
put("humidity", (w, b) -> NumericValue.of(((BiomeInterface) (Object) b).getClimateSettings().downfall()));
|
||||
put("precipitation", (w, b) -> StringValue.of(b.getPrecipitationAt(new BlockPos(0, w.getSeaLevel(), 0)).name().toLowerCase(Locale.ROOT)));
|
||||
//put("depth", (w, b) -> NumericValue.of(b.getDepth()));
|
||||
//put("scale", (w, b) -> NumericValue.of(b.getScale()));
|
||||
put("features", (w, b) -> {
|
||||
|
||||
Registry<ConfiguredFeature<?,?>> registry = w.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE);
|
||||
final Registry<ConfiguredFeature<?, ?>> registry = w.registryAccess().registryOrThrow(Registries.CONFIGURED_FEATURE);
|
||||
return ListValue.wrap(
|
||||
b.getGenerationSettings().features().stream().map(step ->
|
||||
ListValue.wrap(step.stream().map(cfp ->
|
||||
@@ -47,9 +42,5 @@ public class BiomeInfo
|
||||
)
|
||||
);
|
||||
});
|
||||
//put("structures", (w, b) -> {
|
||||
// Registry<ConfiguredStructureFeature<?,?>> registry = w.getRegistryManager().get(Registry.CONFIGURED_STRUCTURE_FEATURE_KEY);
|
||||
// return ListValue.wrap(b.getGenerationSettings().getStructureFeatures().stream().map(str -> ValueConversions.of(registry.getId(str.get()))));
|
||||
//});
|
||||
}};
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package carpet.script.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
@@ -17,7 +18,8 @@ public class EquipmentInventory implements Container
|
||||
);
|
||||
|
||||
LivingEntity mob;
|
||||
public EquipmentInventory(LivingEntity mob)
|
||||
|
||||
public EquipmentInventory(final LivingEntity mob)
|
||||
{
|
||||
this.mob = mob;
|
||||
}
|
||||
@@ -31,20 +33,25 @@ public class EquipmentInventory implements Container
|
||||
@Override
|
||||
public boolean isEmpty()
|
||||
{
|
||||
for (EquipmentSlot slot: slotToSlot)
|
||||
if (!mob.getItemBySlot(slot).isEmpty()) return false;
|
||||
for (final EquipmentSlot slot : slotToSlot)
|
||||
{
|
||||
if (!mob.getItemBySlot(slot).isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItem(int slot)
|
||||
public ItemStack getItem(final int slot)
|
||||
{
|
||||
EquipmentSlot slotSlot;
|
||||
final EquipmentSlot slotSlot;
|
||||
try
|
||||
{
|
||||
slotSlot = slotToSlot.get(slot);
|
||||
}
|
||||
catch (IndexOutOfBoundsException ignored)
|
||||
catch (final IndexOutOfBoundsException ignored)
|
||||
{
|
||||
//going out of the index should be really exceptional
|
||||
return ItemStack.EMPTY;
|
||||
@@ -53,14 +60,14 @@ public class EquipmentInventory implements Container
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeItem(int slot, int amount)
|
||||
public ItemStack removeItem(final int slot, final int amount)
|
||||
{
|
||||
EquipmentSlot slotSlot;
|
||||
final EquipmentSlot slotSlot;
|
||||
try
|
||||
{
|
||||
slotSlot = slotToSlot.get(slot);
|
||||
}
|
||||
catch (IndexOutOfBoundsException ignored)
|
||||
catch (final IndexOutOfBoundsException ignored)
|
||||
{
|
||||
//going out of the index should be really exceptional
|
||||
return ItemStack.EMPTY;
|
||||
@@ -69,32 +76,32 @@ public class EquipmentInventory implements Container
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeItemNoUpdate(int slot)
|
||||
public ItemStack removeItemNoUpdate(final int slot)
|
||||
{
|
||||
EquipmentSlot slotSlot;
|
||||
final EquipmentSlot slotSlot;
|
||||
try
|
||||
{
|
||||
slotSlot = slotToSlot.get(slot);
|
||||
}
|
||||
catch (IndexOutOfBoundsException ignored)
|
||||
catch (final IndexOutOfBoundsException ignored)
|
||||
{
|
||||
//going out of the index should be really exceptional
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
ItemStack previous = mob.getItemBySlot(slotSlot);
|
||||
final ItemStack previous = mob.getItemBySlot(slotSlot);
|
||||
mob.setItemSlot(slotSlot, ItemStack.EMPTY);
|
||||
return previous;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(int slot, ItemStack stack)
|
||||
public void setItem(final int slot, final ItemStack stack)
|
||||
{
|
||||
EquipmentSlot slotSlot;
|
||||
final EquipmentSlot slotSlot;
|
||||
try
|
||||
{
|
||||
slotSlot = slotToSlot.get(slot);
|
||||
}
|
||||
catch (IndexOutOfBoundsException ignored)
|
||||
catch (final IndexOutOfBoundsException ignored)
|
||||
{
|
||||
//going out of the index should be really exceptional
|
||||
return;
|
||||
@@ -109,7 +116,7 @@ public class EquipmentInventory implements Container
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(Player player)
|
||||
public boolean stillValid(final Player player)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -117,7 +124,9 @@ public class EquipmentInventory implements Container
|
||||
@Override
|
||||
public void clearContent()
|
||||
{
|
||||
for (EquipmentSlot slot: slotToSlot)
|
||||
for (final EquipmentSlot slot : slotToSlot)
|
||||
{
|
||||
mob.setItemSlot(slot, ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ public class GlocalFlag extends ThreadLocal<Boolean>
|
||||
{
|
||||
private final boolean initial;
|
||||
|
||||
public GlocalFlag(boolean initial)
|
||||
public GlocalFlag(final boolean initial)
|
||||
{
|
||||
this.initial = initial;
|
||||
}
|
||||
@@ -19,19 +19,20 @@ public class GlocalFlag extends ThreadLocal<Boolean>
|
||||
|
||||
/**
|
||||
* Allows to thread-safely wrap a call while disabling a global flag and setting it back up right after.
|
||||
*
|
||||
* @param action - callback to invoke when the wrapping is all setup
|
||||
* @param <T> - returned value of that action, whatever that might be
|
||||
* @param <T> - returned value of that action, whatever that might be
|
||||
* @return result of the action
|
||||
*/
|
||||
public <T> T getWhileDisabled(Supplier<T> action)
|
||||
public <T> T getWhileDisabled(final Supplier<T> action)
|
||||
{
|
||||
return whileValueReturn(!initial, action);
|
||||
}
|
||||
|
||||
private <T> T whileValueReturn(boolean what, Supplier<T> action)
|
||||
private <T> T whileValueReturn(final boolean what, final Supplier<T> action)
|
||||
{
|
||||
T result;
|
||||
boolean previous;
|
||||
final boolean previous;
|
||||
synchronized (this)
|
||||
{
|
||||
previous = get();
|
||||
@@ -48,11 +49,14 @@ public class GlocalFlag extends ThreadLocal<Boolean>
|
||||
return result;
|
||||
}
|
||||
|
||||
public <T> T runIfEnabled(Supplier<T> action)
|
||||
public <T> T runIfEnabled(final Supplier<T> action)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
if (get() != initial) return null;
|
||||
if (get() != initial)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
set(!initial);
|
||||
}
|
||||
T result;
|
||||
|
||||
@@ -3,27 +3,31 @@ package carpet.script.utils;
|
||||
import carpet.script.exception.InternalExpressionException;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import net.minecraft.ResourceLocationException;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
public class InputValidator {
|
||||
public static String validateSimpleString(String input, boolean strict)
|
||||
public class InputValidator
|
||||
{
|
||||
public static String validateSimpleString(final String input, final boolean strict)
|
||||
{
|
||||
String simplified = input.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9+_]", "");
|
||||
final String simplified = input.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9+_]", "");
|
||||
if (simplified.isEmpty() || (strict && !simplified.equals(input)))
|
||||
{
|
||||
throw new InternalExpressionException("simple name can only contain numbers, letter and _");
|
||||
}
|
||||
return simplified;
|
||||
}
|
||||
|
||||
public static ResourceLocation identifierOf(String string)
|
||||
public static ResourceLocation identifierOf(final String string)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ResourceLocation(string);
|
||||
}
|
||||
catch (ResourceLocationException iie)
|
||||
catch (final ResourceLocationException iie)
|
||||
{
|
||||
throw new InternalExpressionException("Incorrect identifier format '"+string+"': "+iie.getMessage());
|
||||
throw new InternalExpressionException("Incorrect identifier format '" + string + "': " + iie.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
// extracted from import net.minecraft.util.math.noise.PerlinNoiseSampler
|
||||
public class PerlinNoiseSampler {
|
||||
public class PerlinNoiseSampler
|
||||
{
|
||||
protected static final int[][] gradients3d = new int[][]{
|
||||
{1, 1, 0}, {-1, 1, 0}, {1, -1, 0}, {-1, -1, 0},
|
||||
{1, 0, 1}, {-1, 0, 1}, {1, 0, -1}, {-1, 0, -1},
|
||||
@@ -23,49 +24,50 @@ public class PerlinNoiseSampler {
|
||||
public static PerlinNoiseSampler instance = new PerlinNoiseSampler(new Random(0));
|
||||
public static Map<Long, PerlinNoiseSampler> samplers = new Long2ObjectOpenHashMap<>();
|
||||
|
||||
public static PerlinNoiseSampler getPerlin(long aLong)
|
||||
public static PerlinNoiseSampler getPerlin(final long aLong)
|
||||
{
|
||||
if (samplers.size() > 256)
|
||||
{
|
||||
samplers.clear();
|
||||
}
|
||||
return samplers.computeIfAbsent(aLong, seed -> new PerlinNoiseSampler(new Random(seed)));
|
||||
}
|
||||
|
||||
public PerlinNoiseSampler(Random random) {
|
||||
public PerlinNoiseSampler(final Random random)
|
||||
{
|
||||
this.originX = random.nextDouble() * 256.0D;
|
||||
this.originY = random.nextDouble() * 256.0D;
|
||||
this.originZ = random.nextDouble() * 256.0D;
|
||||
this.permutations = new byte[256];
|
||||
|
||||
int j;
|
||||
for(j = 0; j < 256; ++j) {
|
||||
this.permutations[j] = (byte)j;
|
||||
for (j = 0; j < 256; ++j)
|
||||
{
|
||||
this.permutations[j] = (byte) j;
|
||||
}
|
||||
|
||||
for(j = 0; j < 256; ++j) {
|
||||
int k = random.nextInt(256 - j);
|
||||
byte b = this.permutations[j];
|
||||
for (j = 0; j < 256; ++j)
|
||||
{
|
||||
final int k = random.nextInt(256 - j);
|
||||
final byte b = this.permutations[j];
|
||||
this.permutations[j] = this.permutations[j + k];
|
||||
this.permutations[j + k] = b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//3D
|
||||
public double sample3d(double x, double y, double z) {//, double d, double e) {
|
||||
double f = x + this.originX;
|
||||
double g = y + this.originY;
|
||||
double h = z + this.originZ;
|
||||
int i = floor(f);
|
||||
int j = floor(g);
|
||||
int k = floor(h);
|
||||
double l = f - (double)i;
|
||||
double m = g - (double)j;
|
||||
double n = h - (double)k;
|
||||
double o = perlinFade(l);
|
||||
double p = perlinFade(m);
|
||||
double q = perlinFade(n);
|
||||
public double sample3d(final double x, final double y, final double z)
|
||||
{//, double d, double e) {
|
||||
final double f = x + this.originX;
|
||||
final double g = y + this.originY;
|
||||
final double h = z + this.originZ;
|
||||
final int i = floor(f);
|
||||
final int j = floor(g);
|
||||
final int k = floor(h);
|
||||
final double l = f - (double) i;
|
||||
final double m = g - (double) j;
|
||||
final double n = h - (double) k;
|
||||
final double o = perlinFade(l);
|
||||
final double p = perlinFade(m);
|
||||
final double q = perlinFade(n);
|
||||
//double t;
|
||||
/*
|
||||
if (d != 0.0D) {
|
||||
@@ -75,110 +77,127 @@ public class PerlinNoiseSampler {
|
||||
t = 0.0D;
|
||||
}*/
|
||||
//return this.sample(i, j, k, l, m - t, n, o, p, q);
|
||||
return this.sample3d(i, j, k, l, m, n, o, p, q)/2+0.5;
|
||||
return this.sample3d(i, j, k, l, m, n, o, p, q) / 2 + 0.5;
|
||||
}
|
||||
|
||||
private double sample3d(int sectionX, int sectionY, int sectionZ, double localX, double localY, double localZ, double fadeLocalX, double fadeLocalY, double fadeLocalZ) {
|
||||
int i = this.getGradient(sectionX) + sectionY;
|
||||
int j = this.getGradient(i) + sectionZ;
|
||||
int k = this.getGradient(i + 1) + sectionZ;
|
||||
int l = this.getGradient(sectionX + 1) + sectionY;
|
||||
int m = this.getGradient(l) + sectionZ;
|
||||
int n = this.getGradient(l + 1) + sectionZ;
|
||||
double d = grad3d(this.getGradient(j), localX, localY, localZ);
|
||||
double e = grad3d(this.getGradient(m), localX - 1.0D, localY, localZ);
|
||||
double f = grad3d(this.getGradient(k), localX, localY - 1.0D, localZ);
|
||||
double g = grad3d(this.getGradient(n), localX - 1.0D, localY - 1.0D, localZ);
|
||||
double h = grad3d(this.getGradient(j + 1), localX, localY, localZ - 1.0D);
|
||||
double o = grad3d(this.getGradient(m + 1), localX - 1.0D, localY, localZ - 1.0D);
|
||||
double p = grad3d(this.getGradient(k + 1), localX, localY - 1.0D, localZ - 1.0D);
|
||||
double q = grad3d(this.getGradient(n + 1), localX - 1.0D, localY - 1.0D, localZ - 1.0D);
|
||||
private double sample3d(final int sectionX, final int sectionY, final int sectionZ, final double localX, final double localY, final double localZ, final double fadeLocalX, final double fadeLocalY, final double fadeLocalZ)
|
||||
{
|
||||
final int i = this.getGradient(sectionX) + sectionY;
|
||||
final int j = this.getGradient(i) + sectionZ;
|
||||
final int k = this.getGradient(i + 1) + sectionZ;
|
||||
final int l = this.getGradient(sectionX + 1) + sectionY;
|
||||
final int m = this.getGradient(l) + sectionZ;
|
||||
final int n = this.getGradient(l + 1) + sectionZ;
|
||||
final double d = grad3d(this.getGradient(j), localX, localY, localZ);
|
||||
final double e = grad3d(this.getGradient(m), localX - 1.0D, localY, localZ);
|
||||
final double f = grad3d(this.getGradient(k), localX, localY - 1.0D, localZ);
|
||||
final double g = grad3d(this.getGradient(n), localX - 1.0D, localY - 1.0D, localZ);
|
||||
final double h = grad3d(this.getGradient(j + 1), localX, localY, localZ - 1.0D);
|
||||
final double o = grad3d(this.getGradient(m + 1), localX - 1.0D, localY, localZ - 1.0D);
|
||||
final double p = grad3d(this.getGradient(k + 1), localX, localY - 1.0D, localZ - 1.0D);
|
||||
final double q = grad3d(this.getGradient(n + 1), localX - 1.0D, localY - 1.0D, localZ - 1.0D);
|
||||
return lerp3(fadeLocalX, fadeLocalY, fadeLocalZ, d, e, f, g, h, o, p, q);
|
||||
}
|
||||
|
||||
private static double grad3d(int hash, double x, double y, double z) {
|
||||
int i = hash & 15;
|
||||
private static double grad3d(final int hash, final double x, final double y, final double z)
|
||||
{
|
||||
final int i = hash & 15;
|
||||
return dot3d(gradients3d[i], x, y, z);
|
||||
}
|
||||
|
||||
protected static double dot3d(int[] gArr, double x, double y, double z) {
|
||||
return (double)gArr[0] * x + (double)gArr[1] * y + (double)gArr[2] * z;
|
||||
protected static double dot3d(final int[] gArr, final double x, final double y, final double z)
|
||||
{
|
||||
return gArr[0] * x + gArr[1] * y + gArr[2] * z;
|
||||
}
|
||||
|
||||
public static double lerp3(double deltaX, double deltaY, double deltaZ, double d, double e, double f, double g, double h, double i, double j, double k) {
|
||||
public static double lerp3(final double deltaX, final double deltaY, final double deltaZ, final double d, final double e, final double f, final double g, final double h, final double i, final double j, final double k)
|
||||
{
|
||||
return lerp(deltaZ, lerp2(deltaX, deltaY, d, e, f, g), lerp2(deltaX, deltaY, h, i, j, k));
|
||||
}
|
||||
|
||||
//2D
|
||||
public double sample2d(double x, double y) {//, double d, double e) {
|
||||
double f = x + this.originX;
|
||||
double g = y + this.originY;
|
||||
int i = floor(f);
|
||||
int j = floor(g);
|
||||
double l = f - (double)i;
|
||||
double m = g - (double)j;
|
||||
double o = perlinFade(l);
|
||||
double p = perlinFade(m);
|
||||
return this.sample2d(i, j, l, m, o, p)/2+0.5;
|
||||
public double sample2d(final double x, final double y)
|
||||
{
|
||||
final double f = x + this.originX;
|
||||
final double g = y + this.originY;
|
||||
final int i = floor(f);
|
||||
final int j = floor(g);
|
||||
final double l = f - (double) i;
|
||||
final double m = g - (double) j;
|
||||
final double o = perlinFade(l);
|
||||
final double p = perlinFade(m);
|
||||
return this.sample2d(i, j, l, m, o, p) / 2 + 0.5;
|
||||
}
|
||||
|
||||
private double sample2d(int sectionX, int sectionY, double localX, double localY, double fadeLocalX, double fadeLocalY) {
|
||||
int j = this.getGradient(sectionX) + sectionY;
|
||||
int m = this.getGradient(sectionX + 1) + sectionY;
|
||||
double d = grad2d(this.getGradient(j), localX, localY);
|
||||
double e = grad2d(this.getGradient(m), localX - 1.0D, localY);
|
||||
double f = grad2d(this.getGradient(j+1), localX, localY - 1.0D);
|
||||
double g = grad2d(this.getGradient(m+1), localX - 1.0D, localY - 1.0D);
|
||||
private double sample2d(final int sectionX, final int sectionY, final double localX, final double localY, final double fadeLocalX, final double fadeLocalY)
|
||||
{
|
||||
final int j = this.getGradient(sectionX) + sectionY;
|
||||
final int m = this.getGradient(sectionX + 1) + sectionY;
|
||||
final double d = grad2d(this.getGradient(j), localX, localY);
|
||||
final double e = grad2d(this.getGradient(m), localX - 1.0D, localY);
|
||||
final double f = grad2d(this.getGradient(j + 1), localX, localY - 1.0D);
|
||||
final double g = grad2d(this.getGradient(m + 1), localX - 1.0D, localY - 1.0D);
|
||||
|
||||
return lerp2(fadeLocalX, fadeLocalY, d, e, f, g);
|
||||
}
|
||||
|
||||
private static double grad2d(int hash, double x, double y) {
|
||||
int i = hash & 3;
|
||||
private static double grad2d(final int hash, final double x, final double y)
|
||||
{
|
||||
final int i = hash & 3;
|
||||
return dot2d(gradients2d[i], x, y);
|
||||
}
|
||||
|
||||
protected static double dot2d(int[] gArr, double x, double y) {
|
||||
return (double)gArr[0] * x + (double)gArr[1] * y;
|
||||
protected static double dot2d(final int[] gArr, final double x, final double y)
|
||||
{
|
||||
return gArr[0] * x + gArr[1] * y;
|
||||
}
|
||||
|
||||
public static double lerp2(double deltaX, double deltaY, double d, double e, double f, double g) {
|
||||
public static double lerp2(final double deltaX, final double deltaY, final double d, final double e, final double f, final double g)
|
||||
{
|
||||
return lerp(deltaY, lerp(deltaX, d, e), lerp(deltaX, f, g));
|
||||
}
|
||||
|
||||
// 1D
|
||||
public double sample1d(double x) {//, double d, double e) {
|
||||
double f = x + this.originX;
|
||||
int i = floor(f);
|
||||
double l = f - (double)i;
|
||||
double o = perlinFade(l);
|
||||
return this.sample1d(i, l, o)+0.5;
|
||||
public double sample1d(final double x)
|
||||
{
|
||||
final double f = x + this.originX;
|
||||
final int i = floor(f);
|
||||
final double l = f - i;
|
||||
final double o = perlinFade(l);
|
||||
return this.sample1d(i, l, o) + 0.5;
|
||||
}
|
||||
private double sample1d(int sectionX, double localX, double fadeLocalX) {
|
||||
double d = grad1d(this.getGradient(sectionX), localX);
|
||||
double e = grad1d(this.getGradient(sectionX+1), localX - 1.0D);
|
||||
|
||||
private double sample1d(final int sectionX, final double localX, final double fadeLocalX)
|
||||
{
|
||||
final double d = grad1d(this.getGradient(sectionX), localX);
|
||||
final double e = grad1d(this.getGradient(sectionX + 1), localX - 1.0D);
|
||||
return lerp(fadeLocalX, d, e);
|
||||
}
|
||||
|
||||
private static double grad1d(int hash, double x) {
|
||||
return ((hash & 1) == 0)? x:-x;
|
||||
private static double grad1d(final int hash, final double x)
|
||||
{
|
||||
return ((hash & 1) == 0) ? x : -x;
|
||||
}
|
||||
|
||||
public static double lerp(double delta, double first, double second) {
|
||||
public static double lerp(final double delta, final double first, final double second)
|
||||
{
|
||||
return first + delta * (second - first);
|
||||
}
|
||||
|
||||
// shared
|
||||
public int getGradient(int hash) {
|
||||
public int getGradient(final int hash)
|
||||
{
|
||||
return this.permutations[hash & 255] & 255;
|
||||
}
|
||||
|
||||
public static double perlinFade(double d) {
|
||||
public static double perlinFade(final double d)
|
||||
{
|
||||
return d * d * d * (d * (d * 6.0D - 15.0D) + 10.0D);
|
||||
}
|
||||
|
||||
public static int floor(double d) {
|
||||
int i = (int)d;
|
||||
return d < (double)i ? i - 1 : i;
|
||||
public static int floor(final double d)
|
||||
{
|
||||
final int i = (int) d;
|
||||
return d < i ? i - 1 : i;
|
||||
}
|
||||
}
|
||||
@@ -20,15 +20,17 @@ import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.StringValue;
|
||||
import carpet.script.value.Value;
|
||||
|
||||
public class ScarpetJsonDeserializer implements JsonDeserializer<Value>{
|
||||
public class ScarpetJsonDeserializer implements JsonDeserializer<Value>
|
||||
{
|
||||
|
||||
@Override
|
||||
public Value deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
public Value deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
return parseElement(json);
|
||||
}
|
||||
|
||||
private Value parseElement(JsonElement element) throws JsonParseException {
|
||||
|
||||
private Value parseElement(final JsonElement element) throws JsonParseException
|
||||
{
|
||||
if (element.isJsonObject())
|
||||
{
|
||||
return parseMap(element.getAsJsonObject());
|
||||
@@ -44,23 +46,22 @@ public class ScarpetJsonDeserializer implements JsonDeserializer<Value>{
|
||||
return Value.NULL;
|
||||
}
|
||||
|
||||
private Value parseMap(JsonObject jsonMap) throws JsonParseException {
|
||||
Map<Value, Value> map = new HashMap<Value, Value>();
|
||||
jsonMap.entrySet().forEach(entry -> {
|
||||
map.put(new StringValue(entry.getKey()), parseElement(entry.getValue()));
|
||||
});
|
||||
private Value parseMap(final JsonObject jsonMap) throws JsonParseException
|
||||
{
|
||||
final Map<Value, Value> map = new HashMap<>();
|
||||
jsonMap.entrySet().forEach(entry -> map.put(new StringValue(entry.getKey()), parseElement(entry.getValue())));
|
||||
return MapValue.wrap(map);
|
||||
}
|
||||
|
||||
private Value parseList(JsonArray jsonList) throws JsonParseException {
|
||||
List<Value> list = new ArrayList<Value>();
|
||||
jsonList.forEach(elem -> {
|
||||
list.add(parseElement(elem));
|
||||
});
|
||||
private Value parseList(final JsonArray jsonList) throws JsonParseException
|
||||
{
|
||||
final List<Value> list = new ArrayList<>();
|
||||
jsonList.forEach(elem -> list.add(parseElement(elem)));
|
||||
return new ListValue(list);
|
||||
}
|
||||
|
||||
private Value parsePrimitive(JsonPrimitive primitive) throws JsonParseException {
|
||||
|
||||
private Value parsePrimitive(final JsonPrimitive primitive) throws JsonParseException
|
||||
{
|
||||
if (primitive.isString())
|
||||
{
|
||||
return new StringValue(primitive.getAsString());
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -6,7 +6,8 @@ import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
// extracted from import net.minecraft.util.math.noise.SimplexNoiseSampler
|
||||
public class SimplexNoiseSampler extends PerlinNoiseSampler {
|
||||
public class SimplexNoiseSampler extends PerlinNoiseSampler
|
||||
{
|
||||
private static final double sqrt3 = Math.sqrt(3.0D);
|
||||
private static final double SKEW_FACTOR_2D;
|
||||
private static final double UNSKEW_FACTOR_2D;
|
||||
@@ -14,23 +15,30 @@ public class SimplexNoiseSampler extends PerlinNoiseSampler {
|
||||
public static SimplexNoiseSampler instance = new SimplexNoiseSampler(new Random(0));
|
||||
public static Map<Long, SimplexNoiseSampler> samplers = new Long2ObjectOpenHashMap<>();
|
||||
|
||||
public static SimplexNoiseSampler getSimplex(long aLong)
|
||||
public static SimplexNoiseSampler getSimplex(final long aLong)
|
||||
{
|
||||
if (samplers.size() > 256)
|
||||
{
|
||||
samplers.clear();
|
||||
}
|
||||
return samplers.computeIfAbsent(aLong, seed -> new SimplexNoiseSampler(new Random(seed)));
|
||||
}
|
||||
|
||||
public SimplexNoiseSampler(Random random) {
|
||||
public SimplexNoiseSampler(final Random random)
|
||||
{
|
||||
super(random);
|
||||
}
|
||||
|
||||
private double grad(int hash, double x, double y, double z, double d) {
|
||||
private double grad(final int hash, final double x, final double y, final double z, final double d)
|
||||
{
|
||||
double e = d - x * x - y * y - z * z;
|
||||
double g;
|
||||
if (e < 0.0D) {
|
||||
final double g;
|
||||
if (e < 0.0D)
|
||||
{
|
||||
g = 0.0D;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
e *= e;
|
||||
g = e * e * PerlinNoiseSampler.dot3d(PerlinNoiseSampler.gradients3d[hash], x, y, z);
|
||||
}
|
||||
@@ -39,83 +47,94 @@ public class SimplexNoiseSampler extends PerlinNoiseSampler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public double sample2d(double x, double y) {
|
||||
x = x/2;
|
||||
y = y/2;
|
||||
double d = (x + y) * SKEW_FACTOR_2D;
|
||||
int i = PerlinNoiseSampler.floor(x + d);
|
||||
int j = PerlinNoiseSampler.floor(y + d);
|
||||
double e = (double)(i + j) * UNSKEW_FACTOR_2D;
|
||||
double f = (double)i - e;
|
||||
double g = (double)j - e;
|
||||
double h = x - f;
|
||||
double k = y - g;
|
||||
byte n;
|
||||
byte o;
|
||||
if (h > k) {
|
||||
public double sample2d(double x, double y)
|
||||
{
|
||||
x = x / 2;
|
||||
y = y / 2;
|
||||
final double d = (x + y) * SKEW_FACTOR_2D;
|
||||
final int i = PerlinNoiseSampler.floor(x + d);
|
||||
final int j = PerlinNoiseSampler.floor(y + d);
|
||||
final double e = (i + j) * UNSKEW_FACTOR_2D;
|
||||
final double f = i - e;
|
||||
final double g = j - e;
|
||||
final double h = x - f;
|
||||
final double k = y - g;
|
||||
final byte n;
|
||||
final byte o;
|
||||
if (h > k)
|
||||
{
|
||||
n = 1;
|
||||
o = 0;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
n = 0;
|
||||
o = 1;
|
||||
}
|
||||
|
||||
double p = h - (double)n + UNSKEW_FACTOR_2D;
|
||||
double q = k - (double)o + UNSKEW_FACTOR_2D;
|
||||
double r = h - 1.0D + 2.0D * UNSKEW_FACTOR_2D;
|
||||
double s = k - 1.0D + 2.0D * UNSKEW_FACTOR_2D;
|
||||
int t = i & 255;
|
||||
int u = j & 255;
|
||||
int v = this.getGradient(t + this.getGradient(u)) % 12;
|
||||
int w = this.getGradient(t + n + this.getGradient(u + o)) % 12;
|
||||
int z = this.getGradient(t + 1 + this.getGradient(u + 1)) % 12;
|
||||
double aa = this.grad(v, h, k, 0.0D, 0.5D);
|
||||
double ab = this.grad(w, p, q, 0.0D, 0.5D);
|
||||
double ac = this.grad(z, r, s, 0.0D, 0.5D);
|
||||
final double p = h - n + UNSKEW_FACTOR_2D;
|
||||
final double q = k - o + UNSKEW_FACTOR_2D;
|
||||
final double r = h - 1.0D + 2.0D * UNSKEW_FACTOR_2D;
|
||||
final double s = k - 1.0D + 2.0D * UNSKEW_FACTOR_2D;
|
||||
final int t = i & 255;
|
||||
final int u = j & 255;
|
||||
final int v = this.getGradient(t + this.getGradient(u)) % 12;
|
||||
final int w = this.getGradient(t + n + this.getGradient(u + o)) % 12;
|
||||
final int z = this.getGradient(t + 1 + this.getGradient(u + 1)) % 12;
|
||||
final double aa = this.grad(v, h, k, 0.0D, 0.5D);
|
||||
final double ab = this.grad(w, p, q, 0.0D, 0.5D);
|
||||
final double ac = this.grad(z, r, s, 0.0D, 0.5D);
|
||||
//return 70.0D * (aa + ab + ac);
|
||||
return 35.0D * (aa + ab + ac)+0.5;
|
||||
return 35.0D * (aa + ab + ac) + 0.5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double sample3d(double d, double e, double f) {
|
||||
d = d/2;
|
||||
e = e/2;
|
||||
f = f/2;
|
||||
double g = 0.3333333333333333D;
|
||||
double h = (d + e + f) * 0.3333333333333333D;
|
||||
int i = floor(d + h);
|
||||
int j = floor(e + h);
|
||||
int k = floor(f + h);
|
||||
double l = 0.16666666666666666D;
|
||||
double m = (double)(i + j + k) * 0.16666666666666666D;
|
||||
double n = (double)i - m;
|
||||
double o = (double)j - m;
|
||||
double p = (double)k - m;
|
||||
double q = d - n;
|
||||
double r = e - o;
|
||||
double s = f - p;
|
||||
byte z;
|
||||
byte aa;
|
||||
byte ab;
|
||||
byte ac;
|
||||
byte ad;
|
||||
byte bc;
|
||||
if (q >= r) {
|
||||
if (r >= s) {
|
||||
public double sample3d(double d, double e, double f)
|
||||
{
|
||||
d = d / 2;
|
||||
e = e / 2;
|
||||
f = f / 2;
|
||||
//final double g = 0.3333333333333333D;
|
||||
final double h = (d + e + f) * 0.3333333333333333D;
|
||||
final int i = floor(d + h);
|
||||
final int j = floor(e + h);
|
||||
final int k = floor(f + h);
|
||||
//final double l = 0.16666666666666666D;
|
||||
final double m = (i + j + k) * 0.16666666666666666D;
|
||||
final double n = i - m;
|
||||
final double o = j - m;
|
||||
final double p = k - m;
|
||||
final double q = d - n;
|
||||
final double r = e - o;
|
||||
final double s = f - p;
|
||||
final byte z;
|
||||
final byte aa;
|
||||
final byte ab;
|
||||
final byte ac;
|
||||
final byte ad;
|
||||
final byte bc;
|
||||
if (q >= r)
|
||||
{
|
||||
if (r >= s)
|
||||
{
|
||||
z = 1;
|
||||
aa = 0;
|
||||
ab = 0;
|
||||
ac = 1;
|
||||
ad = 1;
|
||||
bc = 0;
|
||||
} else if (q >= s) {
|
||||
}
|
||||
else if (q >= s)
|
||||
{
|
||||
z = 1;
|
||||
aa = 0;
|
||||
ab = 0;
|
||||
ac = 1;
|
||||
ad = 0;
|
||||
bc = 1;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
z = 0;
|
||||
aa = 0;
|
||||
ab = 1;
|
||||
@@ -123,21 +142,27 @@ public class SimplexNoiseSampler extends PerlinNoiseSampler {
|
||||
ad = 0;
|
||||
bc = 1;
|
||||
}
|
||||
} else if (r < s) {
|
||||
}
|
||||
else if (r < s)
|
||||
{
|
||||
z = 0;
|
||||
aa = 0;
|
||||
ab = 1;
|
||||
ac = 0;
|
||||
ad = 1;
|
||||
bc = 1;
|
||||
} else if (q < s) {
|
||||
}
|
||||
else if (q < s)
|
||||
{
|
||||
z = 0;
|
||||
aa = 1;
|
||||
ab = 0;
|
||||
ac = 0;
|
||||
ad = 1;
|
||||
bc = 1;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
z = 0;
|
||||
aa = 1;
|
||||
ab = 0;
|
||||
@@ -146,30 +171,31 @@ public class SimplexNoiseSampler extends PerlinNoiseSampler {
|
||||
bc = 0;
|
||||
}
|
||||
|
||||
double bd = q - (double)z + 0.16666666666666666D;
|
||||
double be = r - (double)aa + 0.16666666666666666D;
|
||||
double bf = s - (double)ab + 0.16666666666666666D;
|
||||
double bg = q - (double)ac + 0.3333333333333333D;
|
||||
double bh = r - (double)ad + 0.3333333333333333D;
|
||||
double bi = s - (double)bc + 0.3333333333333333D;
|
||||
double bj = q - 1.0D + 0.5D;
|
||||
double bk = r - 1.0D + 0.5D;
|
||||
double bl = s - 1.0D + 0.5D;
|
||||
int bm = i & 255;
|
||||
int bn = j & 255;
|
||||
int bo = k & 255;
|
||||
int bp = this.getGradient(bm + this.getGradient(bn + this.getGradient(bo))) % 12;
|
||||
int bq = this.getGradient(bm + z + this.getGradient(bn + aa + this.getGradient(bo + ab))) % 12;
|
||||
int br = this.getGradient(bm + ac + this.getGradient(bn + ad + this.getGradient(bo + bc))) % 12;
|
||||
int bs = this.getGradient(bm + 1 + this.getGradient(bn + 1 + this.getGradient(bo + 1))) % 12;
|
||||
double bt = this.grad(bp, q, r, s, 0.6D);
|
||||
double bu = this.grad(bq, bd, be, bf, 0.6D);
|
||||
double bv = this.grad(br, bg, bh, bi, 0.6D);
|
||||
double bw = this.grad(bs, bj, bk, bl, 0.6D);
|
||||
final double bd = q - z + 0.16666666666666666D;
|
||||
final double be = r - aa + 0.16666666666666666D;
|
||||
final double bf = s - ab + 0.16666666666666666D;
|
||||
final double bg = q - ac + 0.3333333333333333D;
|
||||
final double bh = r - ad + 0.3333333333333333D;
|
||||
final double bi = s - bc + 0.3333333333333333D;
|
||||
final double bj = q - 1.0D + 0.5D;
|
||||
final double bk = r - 1.0D + 0.5D;
|
||||
final double bl = s - 1.0D + 0.5D;
|
||||
final int bm = i & 255;
|
||||
final int bn = j & 255;
|
||||
final int bo = k & 255;
|
||||
final int bp = this.getGradient(bm + this.getGradient(bn + this.getGradient(bo))) % 12;
|
||||
final int bq = this.getGradient(bm + z + this.getGradient(bn + aa + this.getGradient(bo + ab))) % 12;
|
||||
final int br = this.getGradient(bm + ac + this.getGradient(bn + ad + this.getGradient(bo + bc))) % 12;
|
||||
final int bs = this.getGradient(bm + 1 + this.getGradient(bn + 1 + this.getGradient(bo + 1))) % 12;
|
||||
final double bt = this.grad(bp, q, r, s, 0.6D);
|
||||
final double bu = this.grad(bq, bd, be, bf, 0.6D);
|
||||
final double bv = this.grad(br, bg, bh, bi, 0.6D);
|
||||
final double bw = this.grad(bs, bj, bk, bl, 0.6D);
|
||||
return 16.0D * (bt + bu + bv + bw) + 0.5;
|
||||
}
|
||||
|
||||
static {
|
||||
static
|
||||
{
|
||||
SKEW_FACTOR_2D = 0.5D * (sqrt3 - 1.0D);
|
||||
UNSKEW_FACTOR_2D = (3.0D - sqrt3) / 6.0D;
|
||||
}
|
||||
|
||||
@@ -40,11 +40,12 @@ public class SnoopyCommandSource extends CommandSourceStack
|
||||
private final List<Component> chatOutput;
|
||||
private final CommandSigningContext signingContext;
|
||||
|
||||
public SnoopyCommandSource(CommandSourceStack original, Component[] error, List<Component> chatOutput)
|
||||
public SnoopyCommandSource(final CommandSourceStack original, final Component[] error, final List<Component> chatOutput)
|
||||
{
|
||||
super(CommandSource.NULL, original.getPosition(), original.getRotation(), original.getLevel(), CarpetSettings.runPermissionLevel,
|
||||
original.getTextName(), original.getDisplayName(), original.getServer(), original.getEntity(), false,
|
||||
(ctx, succ, res) -> { }, EntityAnchorArgument.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(original.getServer()));
|
||||
(ctx, succ, res) -> {
|
||||
}, EntityAnchorArgument.Anchor.FEET, CommandSigningContext.ANONYMOUS, TaskChainer.immediate(original.getServer()));
|
||||
this.output = CommandSource.NULL;
|
||||
this.position = original.getPosition();
|
||||
this.world = original.getLevel();
|
||||
@@ -53,7 +54,8 @@ public class SnoopyCommandSource extends CommandSourceStack
|
||||
this.name = original.getDisplayName();
|
||||
this.server = original.getServer();
|
||||
this.entity = original.getEntity();
|
||||
this.resultConsumer = (ctx, succ, res) -> { };
|
||||
this.resultConsumer = (ctx, succ, res) -> {
|
||||
};
|
||||
this.entityAnchor = original.getAnchor();
|
||||
this.rotation = original.getRotation();
|
||||
this.error = error;
|
||||
@@ -61,20 +63,22 @@ public class SnoopyCommandSource extends CommandSourceStack
|
||||
this.signingContext = original.getSigningContext();
|
||||
}
|
||||
|
||||
public SnoopyCommandSource(ServerPlayer player, Component[] error, List<Component> output) {
|
||||
public SnoopyCommandSource(final ServerPlayer player, final Component[] error, final List<Component> output)
|
||||
{
|
||||
super(player, player.position(), player.getRotationVector(),
|
||||
player.level instanceof ServerLevel ? (ServerLevel) player.level : null,
|
||||
player.level instanceof final ServerLevel serverLevel ? serverLevel : null,
|
||||
player.server.getProfilePermissions(player.getGameProfile()), player.getName().getString(), player.getDisplayName(),
|
||||
player.level.getServer(), player);
|
||||
this.output = player;
|
||||
this.position = player.position();
|
||||
this.world = player.level instanceof ServerLevel ? (ServerLevel) player.level : null;
|
||||
this.world = player.level instanceof final ServerLevel serverLevel ? serverLevel : null;
|
||||
this.level = player.server.getProfilePermissions(player.getGameProfile());
|
||||
this.simpleName = player.getName().getString();
|
||||
this.name = player.getDisplayName();
|
||||
this.server = player.level.getServer();
|
||||
this.entity = player;
|
||||
this.resultConsumer = (ctx, succ, res) -> { };
|
||||
this.resultConsumer = (ctx, succ, res) -> {
|
||||
};
|
||||
this.entityAnchor = EntityAnchorArgument.Anchor.FEET;
|
||||
this.rotation = player.getRotationVector(); // not a client call really
|
||||
this.error = error;
|
||||
@@ -82,9 +86,10 @@ public class SnoopyCommandSource extends CommandSourceStack
|
||||
this.signingContext = CommandSigningContext.ANONYMOUS;
|
||||
}
|
||||
|
||||
private SnoopyCommandSource(CommandSource output, Vec3 pos, Vec2 rot, ServerLevel world, int level, String simpleName, Component name, MinecraftServer server, @Nullable Entity entity, ResultConsumer<CommandSourceStack> consumer, EntityAnchorArgument.Anchor entityAnchor, CommandSigningContext context,
|
||||
Component[] error, List<Component> chatOutput
|
||||
) {
|
||||
private SnoopyCommandSource(final CommandSource output, final Vec3 pos, final Vec2 rot, final ServerLevel world, final int level, final String simpleName, final Component name, final MinecraftServer server, @Nullable final Entity entity, final ResultConsumer<CommandSourceStack> consumer, final EntityAnchorArgument.Anchor entityAnchor, final CommandSigningContext context,
|
||||
final Component[] error, final List<Component> chatOutput
|
||||
)
|
||||
{
|
||||
super(output, pos, rot, world, level,
|
||||
simpleName, name, server, entity, false,
|
||||
consumer, entityAnchor, context, TaskChainer.immediate(server));
|
||||
@@ -105,33 +110,33 @@ public class SnoopyCommandSource extends CommandSourceStack
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSourceStack withEntity(Entity entity)
|
||||
public CommandSourceStack withEntity(final Entity entity)
|
||||
{
|
||||
return new SnoopyCommandSource(output, position, rotation, world, level, entity.getName().getString(), entity.getDisplayName(), server, entity, resultConsumer, entityAnchor, signingContext, error, chatOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSourceStack withPosition(Vec3 position)
|
||||
public CommandSourceStack withPosition(final Vec3 position)
|
||||
{
|
||||
return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, resultConsumer, entityAnchor, signingContext, error, chatOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSourceStack withRotation(Vec2 rotation)
|
||||
public CommandSourceStack withRotation(final Vec2 rotation)
|
||||
{
|
||||
return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, resultConsumer, entityAnchor, signingContext, error, chatOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSourceStack withCallback(ResultConsumer<CommandSourceStack> consumer)
|
||||
public CommandSourceStack withCallback(final ResultConsumer<CommandSourceStack> consumer)
|
||||
{
|
||||
return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, consumer, entityAnchor, signingContext, error, chatOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSourceStack withCallback(ResultConsumer<CommandSourceStack> consumer, BinaryOperator<ResultConsumer<CommandSourceStack>> binaryOperator)
|
||||
public CommandSourceStack withCallback(final ResultConsumer<CommandSourceStack> consumer, final BinaryOperator<ResultConsumer<CommandSourceStack>> binaryOperator)
|
||||
{
|
||||
ResultConsumer<CommandSourceStack> resultConsumer = binaryOperator.apply(this.resultConsumer, consumer);
|
||||
final ResultConsumer<CommandSourceStack> resultConsumer = binaryOperator.apply(this.resultConsumer, consumer);
|
||||
return this.withCallback(resultConsumer);
|
||||
}
|
||||
|
||||
@@ -140,56 +145,58 @@ public class SnoopyCommandSource extends CommandSourceStack
|
||||
//public ServerCommandSource withSilent() { return this; }
|
||||
|
||||
@Override
|
||||
public CommandSourceStack withPermission(int level)
|
||||
public CommandSourceStack withPermission(final int level)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSourceStack withMaximumPermission(int level)
|
||||
public CommandSourceStack withMaximumPermission(final int level)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSourceStack withAnchor(EntityAnchorArgument.Anchor anchor)
|
||||
public CommandSourceStack withAnchor(final EntityAnchorArgument.Anchor anchor)
|
||||
{
|
||||
return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, resultConsumer, anchor, signingContext, error, chatOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSourceStack withSigningContext(CommandSigningContext commandSigningContext) {
|
||||
public CommandSourceStack withSigningContext(final CommandSigningContext commandSigningContext)
|
||||
{
|
||||
return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, resultConsumer, entityAnchor, commandSigningContext, error, chatOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSourceStack withLevel(ServerLevel world)
|
||||
public CommandSourceStack withLevel(final ServerLevel world)
|
||||
{
|
||||
double d = DimensionType.getTeleportationScale(this.world.dimensionType(), world.dimensionType());
|
||||
Vec3 position = new Vec3(this.position.x * d, this.position.y, this.position.z * d);
|
||||
final double d = DimensionType.getTeleportationScale(this.world.dimensionType(), world.dimensionType());
|
||||
final Vec3 position = new Vec3(this.position.x * d, this.position.y, this.position.z * d);
|
||||
return new SnoopyCommandSource(output, position, rotation, world, level, simpleName, name, server, entity, resultConsumer, entityAnchor, signingContext, error, chatOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSourceStack facing(Vec3 position)
|
||||
public CommandSourceStack facing(final Vec3 position)
|
||||
{
|
||||
Vec3 vec3d = this.entityAnchor.apply(this);
|
||||
double d = position.x - vec3d.x;
|
||||
double e = position.y - vec3d.y;
|
||||
double f = position.z - vec3d.z;
|
||||
double g = (double) Math.sqrt(d * d + f * f);
|
||||
float h = Mth.wrapDegrees((float)(-(Mth.atan2(e, g) * 57.2957763671875D)));
|
||||
float i = Mth.wrapDegrees((float)(Mth.atan2(f, d) * 57.2957763671875D) - 90.0F);
|
||||
final Vec3 vec3d = this.entityAnchor.apply(this);
|
||||
final double d = position.x - vec3d.x;
|
||||
final double e = position.y - vec3d.y;
|
||||
final double f = position.z - vec3d.z;
|
||||
final double g = Math.sqrt(d * d + f * f);
|
||||
final float h = Mth.wrapDegrees((float) (-(Mth.atan2(e, g) * 57.2957763671875D)));
|
||||
final float i = Mth.wrapDegrees((float) (Mth.atan2(f, d) * 57.2957763671875D) - 90.0F);
|
||||
return this.withRotation(new Vec2(h, i));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendFailure(Component message)
|
||||
public void sendFailure(final Component message)
|
||||
{
|
||||
error[0] = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSuccess(Component message, boolean broadcastToOps)
|
||||
public void sendSuccess(final Component message, final boolean broadcastToOps)
|
||||
{
|
||||
chatOutput.add(message);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import net.minecraft.world.level.border.WorldBorder;
|
||||
import net.minecraft.world.level.storage.LevelData;
|
||||
import net.minecraft.world.level.storage.LevelResource;
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@@ -36,15 +37,17 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class SystemInfo {
|
||||
private static final Map<String, Function<CarpetContext,Value>> options = new HashMap<>(){{
|
||||
public class SystemInfo
|
||||
{
|
||||
private static final Map<String, Function<CarpetContext, Value>> options = new HashMap<>()
|
||||
{{
|
||||
put("app_name", c ->
|
||||
{
|
||||
String name = c.host.getName();
|
||||
return name == null?Value.NULL:new StringValue(name);
|
||||
final String name = c.host.getName();
|
||||
return name == null ? Value.NULL : new StringValue(name);
|
||||
});
|
||||
put("app_list", c -> ListValue.wrap(((CarpetScriptHost)c.host).scriptServer().modules.keySet().stream().filter(Objects::nonNull).map(StringValue::new)));
|
||||
put("app_scope", c -> StringValue.of((c.host).isPerUser()?"player":"global"));
|
||||
put("app_list", c -> ListValue.wrap(((CarpetScriptHost) c.host).scriptServer().modules.keySet().stream().filter(Objects::nonNull).map(StringValue::new)));
|
||||
put("app_scope", c -> StringValue.of((c.host).isPerUser() ? "player" : "global"));
|
||||
put("app_players", c -> ListValue.wrap(c.host.getUserList().stream().map(StringValue::new)));
|
||||
|
||||
put("world_name", c -> new StringValue(c.server().getWorldData().getLevelName()));
|
||||
@@ -52,30 +55,33 @@ public class SystemInfo {
|
||||
put("server_motd", c -> StringValue.of(c.server().getMotd()));
|
||||
put("world_path", c -> StringValue.of(c.server().getWorldPath(LevelResource.ROOT).toString()));
|
||||
put("world_folder", c -> {
|
||||
Path serverPath = c.server().getWorldPath(LevelResource.ROOT);
|
||||
int nodeCount = serverPath.getNameCount();
|
||||
if (nodeCount < 2) return Value.NULL;
|
||||
String tlf = serverPath.getName(nodeCount-2).toString();
|
||||
final Path serverPath = c.server().getWorldPath(LevelResource.ROOT);
|
||||
final int nodeCount = serverPath.getNameCount();
|
||||
if (nodeCount < 2)
|
||||
{
|
||||
return Value.NULL;
|
||||
}
|
||||
final String tlf = serverPath.getName(nodeCount - 2).toString();
|
||||
return StringValue.of(tlf);
|
||||
});
|
||||
put("world_dimensions", c -> ListValue.wrap(c.server().levelKeys().stream().map(k -> ValueConversions.of(k.location()))));
|
||||
put("world_spawn_point", c -> {
|
||||
LevelData prop = c.server().overworld().getLevelData();
|
||||
final LevelData prop = c.server().overworld().getLevelData();
|
||||
return ListValue.of(NumericValue.of(prop.getXSpawn()), NumericValue.of(prop.getYSpawn()), NumericValue.of(prop.getZSpawn()));
|
||||
});
|
||||
|
||||
put("world_bottom", c-> new NumericValue(c.level().getMinBuildHeight()));
|
||||
put("world_bottom", c -> new NumericValue(c.level().getMinBuildHeight()));
|
||||
|
||||
put("world_top", c-> new NumericValue(c.level().getMaxBuildHeight()));
|
||||
put("world_top", c -> new NumericValue(c.level().getMaxBuildHeight()));
|
||||
|
||||
put("world_center", c-> {
|
||||
WorldBorder worldBorder = c.level().getWorldBorder();
|
||||
put("world_center", c -> {
|
||||
final WorldBorder worldBorder = c.level().getWorldBorder();
|
||||
return ListValue.fromTriple(worldBorder.getCenterX(), 0, worldBorder.getCenterZ());
|
||||
});
|
||||
|
||||
put("world_size", c -> new NumericValue(c.level().getWorldBorder().getSize() / 2));
|
||||
|
||||
put("world_max_size", c-> new NumericValue( c.level().getWorldBorder().getAbsoluteMaxSize()));
|
||||
put("world_max_size", c -> new NumericValue(c.level().getWorldBorder().getAbsoluteMaxSize()));
|
||||
|
||||
put("world_time", c -> new NumericValue(c.level().getGameTime()));
|
||||
|
||||
@@ -90,133 +96,137 @@ public class SystemInfo {
|
||||
put("game_target", c -> StringValue.of(CarpetSettings.releaseTarget));
|
||||
put("game_protocol", c -> NumericValue.of(SharedConstants.getProtocolVersion()));
|
||||
put("game_major_target", c -> {
|
||||
String [] vers = CarpetSettings.releaseTarget.split("\\.");
|
||||
return NumericValue.of((vers.length > 1)?Integer.parseInt(vers[1]):0);
|
||||
final String[] vers = CarpetSettings.releaseTarget.split("\\.");
|
||||
return NumericValue.of((vers.length > 1) ? Integer.parseInt(vers[1]) : 0);
|
||||
});
|
||||
put("game_minor_target", c -> {
|
||||
String [] vers = CarpetSettings.releaseTarget.split("\\.");
|
||||
return NumericValue.of((vers.length > 2)?Integer.parseInt(vers[2]):0);
|
||||
final String[] vers = CarpetSettings.releaseTarget.split("\\.");
|
||||
return NumericValue.of((vers.length > 2) ? Integer.parseInt(vers[2]) : 0);
|
||||
});
|
||||
put("game_stable", c -> BooleanValue.of(SharedConstants.getCurrentVersion().isStable()));
|
||||
put("game_data_version", c->NumericValue.of(SharedConstants.getCurrentVersion().getDataVersion().getVersion()));
|
||||
put("game_pack_version", c->NumericValue.of(SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA)));
|
||||
put("game_data_version", c -> NumericValue.of(SharedConstants.getCurrentVersion().getDataVersion().getVersion()));
|
||||
put("game_pack_version", c -> NumericValue.of(SharedConstants.getCurrentVersion().getPackVersion(PackType.SERVER_DATA)));
|
||||
|
||||
put("server_ip", c -> StringValue.of(c.server().getLocalIp()));
|
||||
put("server_whitelisted", c -> BooleanValue.of(c.server().isEnforceWhitelist()));
|
||||
put("server_whitelist", c -> {
|
||||
MapValue whitelist = new MapValue(Collections.emptyList());
|
||||
for (String s: c.server().getPlayerList().getWhiteListNames())
|
||||
final MapValue whitelist = new MapValue(Collections.emptyList());
|
||||
for (final String s : c.server().getPlayerList().getWhiteListNames())
|
||||
{
|
||||
whitelist.append(StringValue.of(s));
|
||||
}
|
||||
return whitelist;
|
||||
});
|
||||
put("server_banned_players", c -> {
|
||||
MapValue whitelist = new MapValue(Collections.emptyList());
|
||||
for (String s: c.server().getPlayerList().getBans().getUserList())
|
||||
final MapValue whitelist = new MapValue(Collections.emptyList());
|
||||
for (final String s : c.server().getPlayerList().getBans().getUserList())
|
||||
{
|
||||
whitelist.append(StringValue.of(s));
|
||||
}
|
||||
return whitelist;
|
||||
});
|
||||
put("server_banned_ips", c -> {
|
||||
MapValue whitelist = new MapValue(Collections.emptyList());
|
||||
for (String s: c.server().getPlayerList().getIpBans().getUserList())
|
||||
final MapValue whitelist = new MapValue(Collections.emptyList());
|
||||
for (final String s : c.server().getPlayerList().getIpBans().getUserList())
|
||||
{
|
||||
whitelist.append(StringValue.of(s));
|
||||
}
|
||||
return whitelist;
|
||||
});
|
||||
put("server_dev_environment", c-> BooleanValue.of(FabricLoader.getInstance().isDevelopmentEnvironment()));
|
||||
put("server_dev_environment", c -> BooleanValue.of(FabricLoader.getInstance().isDevelopmentEnvironment()));
|
||||
put("server_mods", c -> {
|
||||
Map<Value, Value> ret = new HashMap<>();
|
||||
for (ModContainer mod : FabricLoader.getInstance().getAllMods())
|
||||
final Map<Value, Value> ret = new HashMap<>();
|
||||
for (final ModContainer mod : FabricLoader.getInstance().getAllMods())
|
||||
{
|
||||
ret.put(new StringValue(mod.getMetadata().getId()), new StringValue(mod.getMetadata().getVersion().getFriendlyString()));
|
||||
}
|
||||
return MapValue.wrap(ret);
|
||||
});
|
||||
put("server_last_tick_times", c -> {
|
||||
//assuming we are in the tick world section
|
||||
//assuming we are in the tick world section
|
||||
// might be off one tick when run in the off tasks or asynchronously.
|
||||
int currentReportedTick = c.server().getTickCount()-1;
|
||||
List<Value> ticks = new ArrayList<>(100);
|
||||
final int currentReportedTick = c.server().getTickCount() - 1;
|
||||
final List<Value> ticks = new ArrayList<>(100);
|
||||
final long[] tickArray = c.server().tickTimes;
|
||||
for (int i=currentReportedTick+100; i > currentReportedTick; i--)
|
||||
for (int i = currentReportedTick + 100; i > currentReportedTick; i--)
|
||||
{
|
||||
ticks.add(new NumericValue((tickArray[i % 100])/1000000.0));
|
||||
ticks.add(new NumericValue((tickArray[i % 100]) / 1000000.0));
|
||||
}
|
||||
return ListValue.wrap(ticks);
|
||||
});
|
||||
|
||||
put("java_max_memory", c -> new NumericValue(Runtime.getRuntime().maxMemory()));
|
||||
put("java_allocated_memory", c -> new NumericValue(Runtime.getRuntime().totalMemory()));
|
||||
put("java_used_memory", c -> new NumericValue(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory()));
|
||||
put("java_used_memory", c -> new NumericValue(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()));
|
||||
put("java_cpu_count", c -> new NumericValue(Runtime.getRuntime().availableProcessors()));
|
||||
put("java_version", c -> StringValue.of(System.getProperty("java.version")));
|
||||
put("java_bits", c -> {
|
||||
for (String property : new String[]{"sun.arch.data.model", "com.ibm.vm.bitmode", "os.arch"})
|
||||
for (final String property : new String[]{"sun.arch.data.model", "com.ibm.vm.bitmode", "os.arch"})
|
||||
{
|
||||
String value = System.getProperty(property);
|
||||
final String value = System.getProperty(property);
|
||||
if (value != null && value.contains("64"))
|
||||
{
|
||||
return new NumericValue(64);
|
||||
|
||||
}
|
||||
}
|
||||
return new NumericValue(32);
|
||||
});
|
||||
put("java_system_cpu_load", c -> {
|
||||
OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(
|
||||
final OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(
|
||||
OperatingSystemMXBean.class);
|
||||
return new NumericValue(osBean.getCpuLoad());
|
||||
});
|
||||
put("java_process_cpu_load", c -> {
|
||||
OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(
|
||||
final OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(
|
||||
OperatingSystemMXBean.class);
|
||||
return new NumericValue(osBean.getProcessCpuLoad());
|
||||
});
|
||||
put("world_carpet_rules", c -> {
|
||||
Collection<CarpetRule<?>> rules = CarpetServer.settingsManager.getCarpetRules();
|
||||
MapValue carpetRules = new MapValue(Collections.emptyList());
|
||||
rules.forEach(rule -> {
|
||||
carpetRules.put(new StringValue(rule.name()), new StringValue(RuleHelper.toRuleString(rule.value())));
|
||||
});
|
||||
final Collection<CarpetRule<?>> rules = CarpetServer.settingsManager.getCarpetRules();
|
||||
final MapValue carpetRules = new MapValue(Collections.emptyList());
|
||||
rules.forEach(rule -> carpetRules.put(new StringValue(rule.name()), new StringValue(RuleHelper.toRuleString(rule.value()))));
|
||||
CarpetServer.extensions.forEach(e -> {
|
||||
SettingsManager manager = e.extensionSettingsManager();
|
||||
if (manager == null) return;
|
||||
|
||||
Collection<CarpetRule<?>> extensionRules = manager.getCarpetRules();
|
||||
extensionRules.forEach(rule -> {
|
||||
carpetRules.put(new StringValue(manager.identifier()+":"+rule.name()), new StringValue(RuleHelper.toRuleString(rule.value())));
|
||||
});
|
||||
final SettingsManager manager = e.extensionSettingsManager();
|
||||
if (manager == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
manager.getCarpetRules().forEach(rule -> carpetRules.put(new StringValue(manager.identifier() + ":" + rule.name()), new StringValue(RuleHelper.toRuleString(rule.value()))));
|
||||
});
|
||||
return carpetRules;
|
||||
});
|
||||
put("world_gamerules", c->{
|
||||
Map<Value, Value> rules = new HashMap<>();
|
||||
put("world_gamerules", c -> {
|
||||
final Map<Value, Value> rules = new HashMap<>();
|
||||
final GameRules gameRules = c.level().getGameRules();
|
||||
GameRules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor() {
|
||||
GameRules.visitGameRuleTypes(new GameRules.GameRuleTypeVisitor()
|
||||
{
|
||||
@Override
|
||||
public <T extends GameRules.Value<T>> void visit(GameRules.Key<T> key, GameRules.Type<T> type) {
|
||||
public <T extends GameRules.Value<T>> void visit(final GameRules.Key<T> key, final GameRules.Type<T> type)
|
||||
{
|
||||
rules.put(StringValue.of(key.getId()), StringValue.of(gameRules.getRule(key).toString()));
|
||||
}
|
||||
});
|
||||
return MapValue.wrap(rules);
|
||||
});
|
||||
put("world_min_spawning_light", c-> NumericValue.of(c.level().dimensionType().monsterSpawnBlockLightLimit()));
|
||||
put("world_min_spawning_light", c -> NumericValue.of(c.level().dimensionType().monsterSpawnBlockLightLimit()));
|
||||
|
||||
put("source_entity", c -> EntityValue.of(c.source().getEntity()));
|
||||
put("source_position", c -> ValueConversions.of(c.source().getPosition()));
|
||||
put("source_dimension", c -> ValueConversions.of(c.level()));
|
||||
put("source_rotation", c -> {
|
||||
Vec2 rotation = c.source().getRotation();
|
||||
final Vec2 rotation = c.source().getRotation();
|
||||
return ListValue.of(new NumericValue(rotation.x), new NumericValue(rotation.y));
|
||||
});
|
||||
|
||||
|
||||
put("scarpet_version", c -> StringValue.of(CarpetSettings.carpetVersion));
|
||||
|
||||
}};
|
||||
public static Value get(String what, CarpetContext cc)
|
||||
|
||||
public static Value get(final String what, final CarpetContext cc)
|
||||
{
|
||||
return options.getOrDefault(what, c -> null).apply(cc);
|
||||
}
|
||||
|
||||
public static Value getAll()
|
||||
{
|
||||
return ListValue.wrap(options.keySet().stream().map(StringValue::of));
|
||||
|
||||
@@ -32,6 +32,7 @@ import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
|
||||
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||
import net.minecraft.world.level.storage.DerivedLevelData;
|
||||
import net.minecraft.world.level.storage.ServerLevelData;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
@@ -42,32 +43,48 @@ import java.util.Set;
|
||||
public class WorldTools
|
||||
{
|
||||
|
||||
public static boolean canHasChunk(ServerLevel world, ChunkPos chpos, Map<String, RegionFile> regionCache, boolean deepcheck)
|
||||
public static boolean canHasChunk(final ServerLevel world, final ChunkPos chpos, final Map<String, RegionFile> regionCache, final boolean deepcheck)
|
||||
{
|
||||
if (world.getChunk(chpos.x, chpos.z, ChunkStatus.STRUCTURE_STARTS, false) != null)
|
||||
{
|
||||
return true;
|
||||
String currentRegionName = "r." + chpos.getRegionX() + "." + chpos.getRegionZ() + ".mca";
|
||||
}
|
||||
final String currentRegionName = "r." + chpos.getRegionX() + "." + chpos.getRegionZ() + ".mca";
|
||||
if (regionCache != null && regionCache.containsKey(currentRegionName))
|
||||
{
|
||||
RegionFile region = regionCache.get(currentRegionName);
|
||||
if (region == null) return false;
|
||||
final RegionFile region = regionCache.get(currentRegionName);
|
||||
if (region == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return region.hasChunk(chpos);
|
||||
}
|
||||
Path regionsFolder = ((MinecraftServerInterface)world.getServer()).getCMSession().getDimensionPath(world.dimension()).resolve("region");
|
||||
Path regionPath = regionsFolder.resolve(currentRegionName);
|
||||
final Path regionsFolder = ((MinecraftServerInterface) world.getServer()).getCMSession().getDimensionPath(world.dimension()).resolve("region");
|
||||
final Path regionPath = regionsFolder.resolve(currentRegionName);
|
||||
if (!regionPath.toFile().exists())
|
||||
{
|
||||
if (regionCache != null) regionCache.put(currentRegionName, null);
|
||||
if (regionCache != null)
|
||||
{
|
||||
regionCache.put(currentRegionName, null);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!deepcheck) return true; // not using cache in this case.
|
||||
if (!deepcheck)
|
||||
{
|
||||
return true; // not using cache in this case.
|
||||
}
|
||||
try
|
||||
{
|
||||
RegionFile region = new RegionFile(regionPath, regionsFolder, true);
|
||||
if (regionCache != null) regionCache.put(currentRegionName, region);
|
||||
final RegionFile region = new RegionFile(regionPath, regionsFolder, true);
|
||||
if (regionCache != null)
|
||||
{
|
||||
regionCache.put(currentRegionName, region);
|
||||
}
|
||||
return region.hasChunk(chpos);
|
||||
}
|
||||
catch (IOException ignored) { }
|
||||
catch (final IOException ignored)
|
||||
{
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
@@ -137,16 +154,16 @@ public class WorldTools
|
||||
return true;
|
||||
}*/
|
||||
|
||||
public static void forceChunkUpdate(BlockPos pos, ServerLevel world)
|
||||
public static void forceChunkUpdate(final BlockPos pos, final ServerLevel world)
|
||||
{
|
||||
ChunkPos chunkPos = new ChunkPos(pos);
|
||||
LevelChunk worldChunk = world.getChunkSource().getChunk(chunkPos.x, chunkPos.z, false);
|
||||
final ChunkPos chunkPos = new ChunkPos(pos);
|
||||
final LevelChunk worldChunk = world.getChunkSource().getChunk(chunkPos.x, chunkPos.z, false);
|
||||
if (worldChunk != null)
|
||||
{
|
||||
List<ServerPlayer> players = world.getChunkSource().chunkMap.getPlayers(chunkPos, false);
|
||||
final List<ServerPlayer> players = world.getChunkSource().chunkMap.getPlayers(chunkPos, false);
|
||||
if (!players.isEmpty())
|
||||
{
|
||||
ClientboundLevelChunkWithLightPacket packet = new ClientboundLevelChunkWithLightPacket(worldChunk, world.getLightEngine(), null, null, false); // false seems to update neighbours as well.
|
||||
final ClientboundLevelChunkWithLightPacket packet = new ClientboundLevelChunkWithLightPacket(worldChunk, world.getLightEngine(), null, null, false); // false seems to update neighbours as well.
|
||||
players.forEach(p -> p.connection.send(packet));
|
||||
}
|
||||
}
|
||||
@@ -155,11 +172,26 @@ public class WorldTools
|
||||
|
||||
private static class NoopWorldGenerationProgressListener implements ChunkProgressListener
|
||||
{
|
||||
@Override public void updateSpawnPos(ChunkPos spawnPos) { }
|
||||
@Override public void onStatusChange(ChunkPos pos, ChunkStatus status) { }
|
||||
@Override
|
||||
public void updateSpawnPos(final ChunkPos spawnPos)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusChange(final ChunkPos pos, final ChunkStatus status)
|
||||
{
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
@Override public void start() { }
|
||||
@Override public void stop() { }
|
||||
@Override
|
||||
public void start()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static final ChunkProgressListener NOOP_LISTENER = new NoopWorldGenerationProgressListener();
|
||||
|
||||
@@ -7,7 +7,8 @@ import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public enum ShapeDirection {
|
||||
public enum ShapeDirection
|
||||
{
|
||||
NORTH,
|
||||
SOUTH,
|
||||
EAST,
|
||||
@@ -17,8 +18,10 @@ public enum ShapeDirection {
|
||||
CAMERA,
|
||||
PLAYER;
|
||||
|
||||
public static ShapeDirection fromString(String direction) {
|
||||
return switch (direction.toLowerCase(Locale.ROOT)) {
|
||||
public static ShapeDirection fromString(final String direction)
|
||||
{
|
||||
return switch (direction.toLowerCase(Locale.ROOT))
|
||||
{
|
||||
case "north" -> NORTH;
|
||||
case "south" -> SOUTH;
|
||||
case "east" -> EAST;
|
||||
@@ -31,8 +34,10 @@ public enum ShapeDirection {
|
||||
};
|
||||
}
|
||||
|
||||
public static void rotatePoseStackByShapeDirection(PoseStack poseStack, ShapeDirection shapeDirection, Camera camera, Vec3 objectPos) {
|
||||
switch (shapeDirection) {
|
||||
public static void rotatePoseStackByShapeDirection(final PoseStack poseStack, final ShapeDirection shapeDirection, final Camera camera, final Vec3 objectPos)
|
||||
{
|
||||
switch (shapeDirection)
|
||||
{
|
||||
case NORTH -> {}
|
||||
case SOUTH -> poseStack.mulPose(Axis.YP.rotationDegrees(180));
|
||||
case EAST -> poseStack.mulPose(Axis.YP.rotationDegrees(270));
|
||||
|
||||
Reference in new issue
Block a user