diff --git a/src/main/java/com/reider745/InnerCoreServer.java b/src/main/java/com/reider745/InnerCoreServer.java index 9866f9ca..51481827 100644 --- a/src/main/java/com/reider745/InnerCoreServer.java +++ b/src/main/java/com/reider745/InnerCoreServer.java @@ -503,11 +503,11 @@ public class InnerCoreServer { } public static String getName() { - return getPropertyString("pack", "Inner Core Test"); + return getPropertyString("pack", "Inner Core"); } public static String getVersionName() { - return getPropertyString("pack-version", "2.3.1b120"); + return getPropertyString("pack-version", "2.3.1b122"); } public static int getVersionCode() { @@ -518,7 +518,7 @@ public class InnerCoreServer { } public static List getVersionsCode() { - final String args = getPropertyString("pack-version-code", "159"); + final String args = getPropertyString("pack-version-code", "162"); final String[] versions_s = args.split(","); final List versions = new ArrayList<>(); diff --git a/src/main/java/com/reider745/event/EventListener.java b/src/main/java/com/reider745/event/EventListener.java index eb9cb16b..e5801eea 100644 --- a/src/main/java/com/reider745/event/EventListener.java +++ b/src/main/java/com/reider745/event/EventListener.java @@ -17,7 +17,9 @@ import cn.nukkit.event.entity.*; import cn.nukkit.event.entity.EntityDamageEvent.DamageCause; import cn.nukkit.event.inventory.CraftItemEvent; import cn.nukkit.event.inventory.InventoryPickupItemEvent; +import cn.nukkit.event.level.ChunkLoadEvent; import cn.nukkit.event.level.ChunkPopulateEvent; +import cn.nukkit.event.level.ChunkUnloadEvent; import cn.nukkit.event.player.*; import cn.nukkit.event.redstone.RedstoneUpdateEvent; import cn.nukkit.event.server.ServerCommandEvent; @@ -33,6 +35,7 @@ import cn.nukkit.level.Location; import cn.nukkit.level.MovingObjectPosition; import cn.nukkit.level.Position; import cn.nukkit.level.format.FullChunk; +import cn.nukkit.level.format.generic.BaseFullChunk; import cn.nukkit.math.Vector3; import cn.nukkit.network.protocol.UpdateBlockPacket; import cn.nukkit.utils.BinaryStream; @@ -564,6 +567,37 @@ public class EventListener implements Listener { event.setCancelled(); } + private static final ArrayList statesEvents = new ArrayList<>(); + public static void addChunkStateChagedListener(int state) { + if(state < -1 || state > 9) return; + if(!statesEvents.contains(state)) statesEvents.add(state); + } + + @EventHandler + public void onChunkLoad(ChunkLoadEvent event){ + final FullChunk chunk = event.getChunk(); + + final int dimension = FakeDimensions.getFakeIdForLevel(event.getLevel()); + final int x = chunk.getX(), z = chunk.getZ(); + + for(int i = 1, preState = 0;i < 10;i+=1, preState++){ + NativeCallback.onChunkStateChaged(dimension, x, z, i, preState, false); + } + } + + @EventHandler + public void onChunkUnload(ChunkUnloadEvent event){ + if(statesEvents.contains(-1) || statesEvents.contains(0)){ + final FullChunk chunk = event.getChunk(); + NativeCallback.onChunkStateChaged( + FakeDimensions.getFakeIdForLevel(event.getLevel()), + chunk.getX(), chunk.getZ(), + 0, 9, + true + ); + } + } + // TODO: onPathNavigationDone // TODO: onBlockSpawnResources diff --git a/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/ChannelInterface.java b/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/ChannelInterface.java index f9f95116..32c0cf62 100644 --- a/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/ChannelInterface.java +++ b/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/ChannelInterface.java @@ -26,6 +26,7 @@ public class ChannelInterface { getCodec(String.class); getCodec(JSONObject.class); getCodec(Scriptable.class); + getCodec(byte[].class); } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/codec/BytesChannelCodec.java b/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/codec/BytesChannelCodec.java new file mode 100644 index 00000000..2fd07846 --- /dev/null +++ b/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/codec/BytesChannelCodec.java @@ -0,0 +1,26 @@ +package com.zhekasmirnov.apparatus.multiplayer.channel.codec; + +import com.zhekasmirnov.apparatus.multiplayer.channel.data.DataChannel; + +public class BytesChannelCodec extends ChannelCodec { + public static final int FORMAT_ID = 4; + + public BytesChannelCodec(DataChannel channel) { + super(channel); + } + + @Override + protected byte[] decode(byte[] data) throws ChannelCodecException { + return data; + } + + @Override + protected byte[] encode(byte[] data) { + return data; + } + + @Override + public int getFormatId() { + return FORMAT_ID; + } +} diff --git a/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/codec/ChannelCodecFactory.java b/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/codec/ChannelCodecFactory.java index e8598d02..a0dfc2d1 100644 --- a/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/codec/ChannelCodecFactory.java +++ b/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/codec/ChannelCodecFactory.java @@ -15,6 +15,9 @@ public class ChannelCodecFactory { if (Scriptable.class.isAssignableFrom(clazz)) { return Scriptable.class; } + if (byte[].class.isAssignableFrom(clazz)) { + return byte[].class; + } return clazz; } @@ -28,6 +31,9 @@ public class ChannelCodecFactory { if (Scriptable.class.isAssignableFrom(clazz)) { return new ScriptableChannelCodec(channel); } + if (byte[].class.isAssignableFrom(clazz)) { + return new BytesChannelCodec(channel); + } throw new IllegalArgumentException("cannot create channel codec for data class: " + clazz.getSimpleName()); } @@ -39,6 +45,8 @@ public class ChannelCodecFactory { return new JsonChannelCodec(channel); case ScriptableChannelCodec.FORMAT_ID: return new ScriptableChannelCodec(channel); + case BytesChannelCodec.FORMAT_ID: + return new BytesChannelCodec(channel); } throw new IllegalArgumentException("cannot create channel codec for format id: " + formatId); } diff --git a/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/codec/ScriptableChannelCodec.java b/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/codec/ScriptableChannelCodec.java index 85707230..a2f2404e 100644 --- a/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/codec/ScriptableChannelCodec.java +++ b/src/main/java/com/zhekasmirnov/apparatus/multiplayer/channel/codec/ScriptableChannelCodec.java @@ -30,6 +30,6 @@ public class ScriptableChannelCodec extends ChannelCodec { @Override public int getFormatId() { - return 0; + return FORMAT_ID; } } diff --git a/src/main/java/com/zhekasmirnov/innercore/api/NativeCallback.java b/src/main/java/com/zhekasmirnov/innercore/api/NativeCallback.java index 71e29387..338a283e 100644 --- a/src/main/java/com/zhekasmirnov/innercore/api/NativeCallback.java +++ b/src/main/java/com/zhekasmirnov/innercore/api/NativeCallback.java @@ -6,6 +6,7 @@ import cn.nukkit.inventory.CraftingGrid; import cn.nukkit.level.Level; import com.reider745.InnerCoreServer; +import com.reider745.api.ClientOnly; import com.reider745.api.ZoteOnly; import com.reider745.entity.EntityMethod; import com.reider745.hooks.PlayerHooks; @@ -829,6 +830,11 @@ public class NativeCallback { } } + @ClientOnly + public static void onOptionsChanged(){ + Callback.invokeCallbackV("OptionsChanged", EMPTY_ARGS); + } + /* WORLD GENERATION CALLBACKS */ public static void onPreChunkPostProcessed(int x, int z) { @@ -847,6 +853,15 @@ public class NativeCallback { Callback.invokeAPICallback("CustomDimensionTransfer", entity, from, to); } + public static void onChunkStateChaged(int dimension, int chunkX, int chunkZ, int state, int preState, boolean discarded) { + ChunkManager.onChunkStateChaged(dimension, chunkX, chunkZ, state, preState, discarded); + } + + @ClientOnly + public static void onLocalChunkStateChaged(int dimension, int chunkX, int chunkZ, int state, int preState, boolean discarded) { + ChunkManager.onLocalChunkStateChaged(dimension, chunkX, chunkZ, state, preState, discarded); + } + /* NETWORK CALLBACKS */ public static void onModdedServerPacketReceived(int formatId) { diff --git a/src/main/java/com/zhekasmirnov/innercore/api/NativeOptions.java b/src/main/java/com/zhekasmirnov/innercore/api/NativeOptions.java new file mode 100644 index 00000000..b1ab191b --- /dev/null +++ b/src/main/java/com/zhekasmirnov/innercore/api/NativeOptions.java @@ -0,0 +1,131 @@ +package com.zhekasmirnov.innercore.api; + +import com.reider745.InnerCoreServer; +import com.reider745.api.ClientOnly; + +@ClientOnly +public class NativeOptions { + protected static long getOptionByName(String name){ + InnerCoreServer.useClientMethod("NativeOptions.getOptionByName"); + return 0; + } + + protected static int getType(long ptr){ + InnerCoreServer.useClientMethod("NativeOptions.getType"); + return OptionType.NONE; + } + + protected static float getFloat(long ptr){ + InnerCoreServer.useClientMethod("NativeOptions.getType"); + return 0; + } + protected static String getString(long ptr){ + InnerCoreServer.useClientMethod("NativeOptions.getType"); + return ""; + } + protected static int getInt(long ptr){ + InnerCoreServer.useClientMethod("NativeOptions.getType"); + return 0; + } + protected static boolean getBool(long ptr){ + InnerCoreServer.useClientMethod("NativeOptions.getType"); + return false; + } + + protected static float getFloatMin(long ptr){ + InnerCoreServer.useClientMethod("NativeOptions.getType"); + return 0; + } + protected static float getFloatMax(long ptr){ + InnerCoreServer.useClientMethod("NativeOptions.getType"); + return 0; + } + + protected static int getIntMin(long ptr){ + InnerCoreServer.useClientMethod("NativeOptions.getType"); + return 0; + } + protected static int getIntMax(long ptr){ + InnerCoreServer.useClientMethod("NativeOptions.getType"); + return 0; + } + + protected static boolean canModify(long ptr){ + InnerCoreServer.useClientMethod("NativeOptions.getType"); + return false; + } + + public static String[] getOptions(){ + InnerCoreServer.useClientMethod("NativeOptions.getType"); + return new String[]{}; + } + + public static class OptionType { + public static final int NONE = 0; + public static final int BOOLEAN = 1; + public static final int FLOAT = 2; + public static final int FLOAT_SLIDER = 3; + public static final int STRING = 4; + public static final int INT = 5; + public static final int INT_SLIDER = 6; + } + + public static class Option { + private final long ptr; + + protected Option(long ptr) { + this.ptr = ptr; + } + + public int getType(){ + return NativeOptions.getType(ptr); + } + + public boolean canModify(){ + return NativeOptions.canModify(ptr); + } + + public long getPointer() { + return ptr; + } + + public float getFloat(){ + return NativeOptions.getFloat(ptr); + } + + public String getString(){ + return NativeOptions.getString(ptr); + } + + public int getInt(){ + return NativeOptions.getInt(ptr); + } + + public boolean getBoolean(){ + return NativeOptions.getBool(ptr); + } + + public float getFloatMin(){ + return NativeOptions.getFloatMin(ptr); + } + + public float getFloatMax(){ + return NativeOptions.getFloatMax(ptr); + } + + public int getIntMin(){ + return NativeOptions.getIntMin(ptr); + } + + public int getIntMax(){ + return NativeOptions.getIntMax(ptr); + } + } + + public static Option get(String name){ + long ptr = getOptionByName(name); + if(ptr != -1) + return new Option(ptr); + return null; + } +} \ No newline at end of file diff --git a/src/main/java/com/zhekasmirnov/innercore/api/mod/adaptedscript/AdaptedScriptAPI.java b/src/main/java/com/zhekasmirnov/innercore/api/mod/adaptedscript/AdaptedScriptAPI.java index c142790f..72c9256d 100644 --- a/src/main/java/com/zhekasmirnov/innercore/api/mod/adaptedscript/AdaptedScriptAPI.java +++ b/src/main/java/com/zhekasmirnov/innercore/api/mod/adaptedscript/AdaptedScriptAPI.java @@ -39,6 +39,7 @@ import com.zhekasmirnov.innercore.api.nbt.NativeCompoundTag; import com.zhekasmirnov.innercore.api.nbt.NativeListTag; import com.zhekasmirnov.innercore.api.nbt.NbtDataType; import com.zhekasmirnov.innercore.api.particles.ParticleRegistry; +import com.zhekasmirnov.innercore.api.runtime.ChunkManager; import com.zhekasmirnov.innercore.api.runtime.LevelInfo; import com.zhekasmirnov.innercore.api.runtime.MainThreadQueue; import com.zhekasmirnov.innercore.api.runtime.other.ArmorRegistry; @@ -222,6 +223,16 @@ public class AdaptedScriptAPI extends API { } } + @JSStaticFunction + public static void addListenerChunkStateChaged(Function listener, NativeArray states){ + ChunkManager.addListenerChunkStateChaged(listener, states); + } + + @JSStaticFunction + public static void addLocalListenerChunkStateChaged(Function listener, NativeArray states){ + ChunkManager.addLocalListenerChunkStateChaged(listener, states); + } + @APIStaticModule public static class Level { @JSStaticFunction @@ -2396,6 +2407,18 @@ public class AdaptedScriptAPI extends API { MainThreadQueue.localThread.enqueue(action); } + @APIStaticModule + public static class MCOptions { + @JSStaticFunction + public static NativeOptions.Option get(String name){ + return NativeOptions.get(name); + } + + public static NativeArray getOptions(){ + return new NativeArray(NativeOptions.getOptions()); + } + } + @APIStaticModule public static class MCSystem { @JSStaticFunction diff --git a/src/main/java/com/zhekasmirnov/innercore/api/mod/recipes/workbench/WorkbenchRecipe.java b/src/main/java/com/zhekasmirnov/innercore/api/mod/recipes/workbench/WorkbenchRecipe.java index 34a85c37..9573734a 100644 --- a/src/main/java/com/zhekasmirnov/innercore/api/mod/recipes/workbench/WorkbenchRecipe.java +++ b/src/main/java/com/zhekasmirnov/innercore/api/mod/recipes/workbench/WorkbenchRecipe.java @@ -221,11 +221,6 @@ public abstract class WorkbenchRecipe { return api.isPrevented() ? null : result; } - @Deprecated(since = "Zote") - public ItemInstance provideRecipe(WorkbenchField field) { - return provideRecipeForPlayer(field, NativeAPI.getPlayer()); - } - private String prefix; diff --git a/src/main/java/com/zhekasmirnov/innercore/api/runtime/ChunkManager.java b/src/main/java/com/zhekasmirnov/innercore/api/runtime/ChunkManager.java new file mode 100644 index 00000000..5bd1d200 --- /dev/null +++ b/src/main/java/com/zhekasmirnov/innercore/api/runtime/ChunkManager.java @@ -0,0 +1,95 @@ +package com.zhekasmirnov.innercore.api.runtime; + +import com.reider745.event.EventListener; +import com.zhekasmirnov.apparatus.util.Java8BackComp; +import com.zhekasmirnov.innercore.mod.executable.Compiler; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.Function; +import org.mozilla.javascript.NativeArray; +import org.mozilla.javascript.Scriptable; + +import java.util.HashMap; +import java.util.LinkedList; + +public class ChunkManager { + public static void addChunkStateChagedListener(int state){ + EventListener.addChunkStateChagedListener(state); + } + + public interface IChunkStateChanged { + void onChunkStateChaged(int chunkX, int chunkZ, int dimension, int preState, int state, boolean discarded); + } + + private static final HashMap> serverStatesListener = new HashMap<>(); + private static final HashMap> localStatesListener = new HashMap<>(); + + private static final HashMap> serverJsStatesListener = new HashMap<>(); + private static final HashMap> localJsStatesListener = new HashMap<>(); + + public static void addListenerChunkStateChaged(IChunkStateChanged changed, int[] states){ + for(int state : states) + Java8BackComp.computeIfAbsent(serverStatesListener, state, _state -> { + addChunkStateChagedListener(state); + return new LinkedList<>(); + }).add(changed); + } + + public static void addListenerChunkStateChaged(Function changed, NativeArray states){ + for(int i = 0;i < states.size();i++) { + int state = ((Number) states.get(i)).intValue(); + + Java8BackComp.computeIfAbsent(serverJsStatesListener, state, _state -> { + addChunkStateChagedListener(state); + return new LinkedList<>(); + }).add(changed); + } + } + + public static void addLocalListenerChunkStateChaged(IChunkStateChanged changed, int[] states){ + for(int state : states) + Java8BackComp.computeIfAbsent(localStatesListener, state, _state -> { + addChunkStateChagedListener(state); + return new LinkedList<>(); + }).add(changed); + } + + public static void addLocalListenerChunkStateChaged(Function changed, NativeArray states){ + for(int i = 0;i < states.size();i++) { + int state = ((Number) states.get(i)).intValue(); + + Java8BackComp.computeIfAbsent(localJsStatesListener, state, _state -> { + addChunkStateChagedListener(state); + return new LinkedList<>(); + }).add(changed); + } + } + + private static final LinkedList EMPTY_LISTENERS = new LinkedList<>(); + private static final LinkedList EMPTY_FUNCTION = new LinkedList<>(); + + public static void onChunkStateChaged(int dimension, int chunkX, int chunkZ, int state, int preState, boolean discarded){ + for(IChunkStateChanged changed : serverStatesListener.getOrDefault(state, EMPTY_LISTENERS)) + changed.onChunkStateChaged(chunkX, chunkZ, dimension, preState, state, discarded); + + final Context context = Compiler.assureContextForCurrentThread(); + final Object[] args = new Object[]{chunkX, chunkZ, dimension, preState, state, discarded}; + + for(Function changed : serverJsStatesListener.getOrDefault(state, EMPTY_FUNCTION)) { + final Scriptable parent = changed.getParentScope(); + changed.call(context, parent, parent, args); + } + } + + public static void onLocalChunkStateChaged(int dimension, int chunkX, int chunkZ, int state, int preState, boolean discarded){ + for(IChunkStateChanged changed : localStatesListener.getOrDefault(state, EMPTY_LISTENERS)) + changed.onChunkStateChaged(chunkX, chunkZ, dimension, preState, state, discarded); + + final Context context = Compiler.assureContextForCurrentThread(); + final Object[] args = new Object[]{chunkX, chunkZ, dimension, preState, state, discarded}; + + for(Function changed : localJsStatesListener.getOrDefault(state, EMPTY_FUNCTION)) { + final Scriptable parent = changed.getParentScope(); + changed.call(context, parent, parent, args); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/zhekasmirnov/innercore/api/unlimited/BlockVariant.java b/src/main/java/com/zhekasmirnov/innercore/api/unlimited/BlockVariant.java index 29e87460..affc5a0f 100644 --- a/src/main/java/com/zhekasmirnov/innercore/api/unlimited/BlockVariant.java +++ b/src/main/java/com/zhekasmirnov/innercore/api/unlimited/BlockVariant.java @@ -25,13 +25,26 @@ public class BlockVariant { public BlockVariant(int uid, int data, String name, String[] textures, int[] textureIds, boolean inCreative) { this.name = name; - this.textures = textures; - this.textureIds = textureIds; this.inCreative = inCreative; this.uid = uid; this.data = data; + this.textures = new String[6]; + this.textureIds = new int[6]; + + String lastTexture = "missing_block"; + int lastMeta = 0; + + for (int i = 0; i < 6; i++) + if(i < textures.length) { + this.textures[i] = lastTexture = textures[i]; + this.textureIds[i] = lastMeta = textureIds[i]; + } else { + this.textures[i] = lastTexture; + this.textureIds[i] = lastMeta; + } + validate(); } @@ -74,14 +87,7 @@ public class BlockVariant { NameTranslation.sendNameToGenerateCache(uid, data, name); } - private void validate() { - for (int i = 0; i < 6; i++) { - if (textures[i] == null) { - textures[i] = "missing_block"; - textureIds[i] = 0; - } - } - } + private void validate() {} public GuiBlockModel getGuiBlockModel() { return GuiBlockModel.createModelForBlockVariant(this); diff --git a/src/main/resources/innercore/coreengine/core-engine.dev.js b/src/main/resources/innercore/coreengine/core-engine.dev.js index 171d8a8a..6ae88ec8 100755 --- a/src/main/resources/innercore/coreengine/core-engine.dev.js +++ b/src/main/resources/innercore/coreengine/core-engine.dev.js @@ -463,6 +463,12 @@ var GameAPI = { isDedicatedServer: function(){ return isDedicatedServer(); }, + getOption: function(name){ + return MCOptions.get(name); + }, + getOptions: function(){ + return MCOptions.getOptions(); + }, prevent: function() { preventDefault(); }, @@ -1645,7 +1651,7 @@ var BlockRegistry = { }); // vanilla bucket is patched in such way, that it will call this callback only for custom liquids in front of dispenser - ItemRegistry.registerDispenseFunction(emptyId, function(coords, item, region, slot) { + Callback.addCallback("ItemDispensed", function(coords, item, region, slot) { if (item.data !== 0) return; var dispenser = region.getBlockEntity(coords.x, coords.y, coords.z); if (!dispenser) return; @@ -3378,6 +3384,12 @@ var WorldAPI = { Level.setBlockChangeCallbackEnabled(id, enabled); }, blockChangeCallbacks: [], + addListenerChunkStateChaged: function(listener, states) { + Level.addListenerChunkStateChaged(listener, states); + }, + addLocalListenerChunkStateChaged: function(listener, states) { + Level.addLocalListenerChunkStateChaged(listener, states); + }, registerBlockChangeCallback: function(ids, callback) { if (!Array.isArray(ids)) { ids = [ids]; diff --git a/src/main/resources/zotecore.yml b/src/main/resources/zotecore.yml index 68fd3def..b20aae2a 100644 --- a/src/main/resources/zotecore.yml +++ b/src/main/resources/zotecore.yml @@ -1,8 +1,8 @@ # Change resolution of pack that client should have to log into server. # However, no deprecated or unimplemented methods will be added. -pack: Inner Core Test -pack-version: 2.3.0b120 -pack-version-code: 160 +pack: Inner Core +pack-version: 2.3.0b122 +pack-version-code: 162 # Sets the list of mods and configs to load, you can specify # name, folder name of a modpack from /modpacks or a path.