Update to MC 1.14 / Fabric

This commit is contained in:
Jonas Herzig
2019-05-04 14:37:00 +02:00
parent 17fe5b345f
commit 3d009e45c7
151 changed files with 3963 additions and 1455 deletions

View File

@@ -2,19 +2,33 @@ package com.replaymod.core;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import de.johni0702.minecraft.gui.utils.EventRegistrations;
import com.replaymod.core.versions.MCVer;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.crash.ReportedException;
import net.minecraftforge.eventbus.api.SubscribeEvent;
//#if MC>=11400
//$$ import com.replaymod.core.versions.LangResourcePack;
//$$ import net.fabricmc.fabric.api.client.keybinding.FabricKeyBinding;
//$$ import net.minecraft.client.util.InputUtil;
//$$ import net.minecraft.util.Identifier;
//$$ import static com.replaymod.core.ReplayMod.MOD_ID;
//#else
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.gameevent.InputEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
//#endif
//#if MC>=11300
import com.replaymod.core.events.KeyBindingEventCallback;
import com.replaymod.core.events.KeyEventCallback;
import com.replaymod.core.events.PreRenderCallback;
//#else
//$$ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
//$$ import net.minecraftforge.fml.common.gameevent.InputEvent;
//$$ import net.minecraftforge.fml.common.gameevent.TickEvent;
//$$ import org.lwjgl.input.Keyboard;
//$$ import static com.replaymod.core.versions.MCVer.FML_BUS;
//#endif
import java.util.Collection;
@@ -22,7 +36,12 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class KeyBindingRegistry {
public class KeyBindingRegistry extends EventRegistrations {
private static final String CATEGORY = "replaymod.title";
//#if MC>=11400
//$$ static { net.fabricmc.fabric.api.client.keybinding.KeyBindingRegistry.INSTANCE.addCategory(CATEGORY); }
//#endif
private Map<String, KeyBinding> keyBindings = new HashMap<String, KeyBinding>();
private Multimap<KeyBinding, Runnable> keyBindingHandlers = ArrayListMultimap.create();
private Multimap<KeyBinding, Runnable> repeatedKeyBindingHandlers = ArrayListMultimap.create();
@@ -39,9 +58,19 @@ public class KeyBindingRegistry {
private KeyBinding registerKeyBinding(String name, int keyCode) {
KeyBinding keyBinding = keyBindings.get(name);
if (keyBinding == null) {
keyBinding = new KeyBinding(name, keyCode, "replaymod.title");
keyBindings.put(name, keyBinding);
//#if MC>=11400
//$$ if (keyCode == 0) {
//$$ keyCode = -1;
//$$ }
//$$ Identifier id = new Identifier(MOD_ID, name.substring(LangResourcePack.LEGACY_KEY_PREFIX.length()));
//$$ FabricKeyBinding fabricKeyBinding = FabricKeyBinding.Builder.create(id, InputUtil.Type.KEYSYM, keyCode, CATEGORY).build();
//$$ net.fabricmc.fabric.api.client.keybinding.KeyBindingRegistry.INSTANCE.register(fabricKeyBinding);
//$$ keyBinding = fabricKeyBinding;
//#else
keyBinding = new KeyBinding(name, keyCode, CATEGORY);
ClientRegistry.registerKeyBinding(keyBinding);
//#endif
keyBindings.put(name, keyBinding);
}
return keyBinding;
}
@@ -54,17 +83,23 @@ public class KeyBindingRegistry {
return Collections.unmodifiableMap(keyBindings);
}
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent event) {
handleKeyBindings();
handleRaw();
}
@SubscribeEvent
public void onTick(TickEvent.RenderTickEvent event) {
if (event.phase != TickEvent.Phase.START) return;
handleRepeatedKeyBindings();
}
//#if MC>=11300
{ on(KeyBindingEventCallback.EVENT, this::handleKeyBindings); }
{ on(KeyEventCallback.EVENT, (keyCode, scanCode, action, modifiers) -> handleRaw(keyCode, action)); }
{ on(PreRenderCallback.EVENT, this::handleRepeatedKeyBindings); }
//#else
//$$ @SubscribeEvent
//$$ public void onKeyInput(InputEvent.KeyInputEvent event) {
//$$ handleKeyBindings();
//$$ handleRaw();
//$$ }
//$$
//$$ @SubscribeEvent
//$$ public void onTick(TickEvent.RenderTickEvent event) {
//$$ if (event.phase != TickEvent.Phase.START) return;
//$$ handleRepeatedKeyBindings();
//$$ }
//#endif
public void handleRepeatedKeyBindings() {
for (Map.Entry<KeyBinding, Collection<Runnable>> entry : repeatedKeyBindingHandlers.asMap().entrySet()) {
@@ -96,9 +131,13 @@ public class KeyBindingRegistry {
}
}
public void handleRaw() {
//int keyCode = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey();
int keyCode = -1; // FIXME
//#if MC>=11300
private void handleRaw(int keyCode, int action) {
if (action != 0) return;
//#else
//$$ private void handleRaw() {
//$$ int keyCode = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey();
//#endif
for (final Runnable runnable : rawHandlers.get(keyCode)) {
try {
runnable.run();

View File

@@ -26,6 +26,7 @@ package com.replaymod.core;
//$$
//$$ public LoadingPlugin() {
//$$ MixinBootstrap.init();
//$$ Mixins.addConfiguration("mixins.core.replaymod.json");
//$$ Mixins.addConfiguration("mixins.recording.replaymod.json");
//$$ Mixins.addConfiguration("mixins.render.replaymod.json");
//$$ Mixins.addConfiguration("mixins.render.blend.replaymod.json");

View File

@@ -21,10 +21,26 @@ import de.johni0702.minecraft.gui.container.GuiScreen;
import lombok.Getter;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import org.apache.commons.io.Charsets;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.util.text.TextFormatting;
import org.apache.commons.io.FileUtils;
//#if MC>=11400
//$$ import com.github.steveice10.mc.protocol.MinecraftConstants;
//$$ import com.replaymod.core.versions.LangResourcePack;
//$$ import net.fabricmc.api.ClientModInitializer;
//$$ import net.fabricmc.loader.api.FabricLoader;
//$$ import net.minecraft.SharedConstants;
//$$ import net.minecraft.client.options.GameOption;
//$$ import net.minecraft.resource.DirectoryResourcePack;
//$$ import net.minecraft.resource.ResourcePackCreator;
//$$ import net.minecraft.resource.ResourcePackContainer;
//#else
import net.minecraftforge.eventbus.api.SubscribeEvent;
//#if MC>=11300
import com.replaymod.core.versions.LangResourcePack;
import net.minecraft.resources.FolderPack;
@@ -41,28 +57,16 @@ import net.minecraftforge.versions.mcp.MCPVersion;
//$$ import net.minecraftforge.common.config.Configuration;
//#endif
//#if MC>=10904
import net.minecraft.util.text.*;
//#else
//$$ import net.minecraft.util.ChatComponentText;
//$$ import net.minecraft.util.ChatComponentTranslation;
//$$ import net.minecraft.util.ChatStyle;
//$$ import net.minecraft.util.EnumChatFormatting;
//$$ import net.minecraft.util.IChatComponent;
//#endif
//#if MC>=10800
import net.minecraft.client.GameSettings;
//#endif
//#if MC>=11300
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModList;
//#else
//$$ import net.minecraftforge.fml.common.Loader;
//$$ import net.minecraftforge.fml.common.Mod.EventHandler;
//$$ import net.minecraftforge.fml.common.Mod.Instance;
//$$ import net.minecraftforge.fml.common.ModContainer;
//$$ import net.minecraftforge.fml.common.event.FMLInitializationEvent;
//$$ import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
//#if MC>=10800
@@ -75,11 +79,13 @@ import net.minecraftforge.fml.ModList;
//#endif
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.gameevent.TickEvent;
//#endif
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -88,6 +94,7 @@ import java.util.concurrent.FutureTask;
import static com.replaymod.core.versions.MCVer.*;
//#if MC<11400
//#if MC>=11300
@Mod(ReplayMod.MOD_ID)
//#else
@@ -102,22 +109,24 @@ import static com.replaymod.core.versions.MCVer.*;
//#endif
//$$ guiFactory = "com.replaymod.core.gui.GuiFactory")
//#endif
public class ReplayMod implements Module {
public static ModContainer getContainer() {
//#if MC>=11300
return ModList.get().getModContainerById(MOD_ID).get();
//#else
//$$ return Loader.instance().getIndexedModList().get(MOD_ID);
//#endif
public class ReplayMod implements
//#if MC>=11400
//$$ ClientModInitializer,
//#endif
}
Module
{
@Getter(lazy = true)
//#if MC>=11400
//$$ private static final String minecraftVersion = MinecraftClient.getInstance().getGame().getVersion().getName();
//#else
//#if MC>=11300
private static final String minecraftVersion = MCPVersion.getMCVersion();
//#else
//$$ private static final String minecraftVersion = Loader.MC_VERSION;
//#endif
//#endif
public static final String MOD_ID = "replaymod";
@@ -152,9 +161,26 @@ public class ReplayMod implements Module {
public ReplayMod() {
I18n.setI18n(net.minecraft.client.resources.I18n::format);
//#if MC>=11400
//$$ // Check Minecraft protocol version for compatibility
//$$ int supportedProtocol = MinecraftConstants.PROTOCOL_VERSION;
//$$ int actualProtocol = SharedConstants.getGameVersion().getProtocolVersion();
//$$ if (supportedProtocol != actualProtocol) {
//$$ throw new UnsupportedOperationException(String.format(
//$$ "Unsupported Minecraft version, supporting protocol version %s (%s) but actual version is %s (%s).",
//$$ supportedProtocol, MinecraftConstants.GAME_VERSION,
//$$ actualProtocol, SharedConstants.getGameVersion().getName()
//$$ ));
//$$ }
//#endif
//#if MC>=11400
//$$ // Not needed on fabric, using MixinModResourcePackUtil instead. Could in theory also use it on 1.13 but it already works as is.
//#else
//#if MC>=11300
DeferredWorkQueue.runLater(() -> MCVer.getMinecraft().getResourcePackList().addPackFinder(new LangResourcePack.Finder()));
//#endif
//#endif
// Register all RM modules
modules.add(this);
@@ -198,8 +224,14 @@ public class ReplayMod implements Module {
return folder;
}
//#ifdef DEV_ENV
static { // Note: even preInit is too late and we'd have to issue another resource reload
//#ifdef DEV_ENV
//noinspection ConstantConditions
if (true) {
//#else
//$$ //noinspection ConstantConditions
//$$ if (false) {
//#endif
@SuppressWarnings("unchecked")
//#if MC>=11300
FolderPack jGuiResourcePack = new FolderPack(new File("../jGui/src/main/resources")) {
@@ -217,7 +249,13 @@ public class ReplayMod implements Module {
//#endif
} catch (IOException e) {
if ("pack.mcmeta".equals(resourceName)) {
return new ByteArrayInputStream(("{\"pack\": {\"description\": \"dummy pack for jGui resources in dev-env\", \"pack_format\": 1}}").getBytes(Charsets.UTF_8));
//#if MC>=11400
//$$ int version = 4;
//#else
int version = 1;
//#endif
return new ByteArrayInputStream(("{\"pack\": {\"description\": \"dummy pack for jGui resources in dev-env\", \"pack_format\": "
+ version + "}}").getBytes(StandardCharsets.UTF_8));
}
throw e;
}
@@ -241,7 +279,7 @@ public class ReplayMod implements Module {
//$$ return super.getInputStreamByName(resourceName);
//$$ } catch (IOException e) {
//$$ if ("pack.mcmeta".equals(resourceName)) {
//$$ return new ByteArrayInputStream(("{\"pack\": {\"description\": \"dummy pack for mod resources in dev-env\", \"pack_format\": 1}}").getBytes(Charsets.UTF_8));
//$$ return new ByteArrayInputStream(("{\"pack\": {\"description\": \"dummy pack for mod resources in dev-env\", \"pack_format\": 1}}").getBytes(StandardCharsets.UTF_8));
//$$ }
//$$ throw e;
//$$ }
@@ -249,9 +287,16 @@ public class ReplayMod implements Module {
//$$ };
//$$ defaultResourcePacks.add(mainResourcePack);
//#endif
}
//#endif
}}
//#if MC>=11400
//$$ @Override
//$$ public void onInitializeClient() {
//$$ modules.forEach(Module::initCommon);
//$$ modules.forEach(Module::initClient);
//$$ modules.forEach(m -> m.registerKeyBindings(keyBindingRegistry));
//$$ }
//#else
//#if MC>=11300
{
FMLJavaModLoadingContext.get().getModEventBus().addListener((FMLCommonSetupEvent event) -> modules.forEach(Module::initCommon));
@@ -266,6 +311,7 @@ public class ReplayMod implements Module {
//$$ modules.forEach(m -> m.registerKeyBindings(keyBindingRegistry));
//$$ }
//#endif
//#endif
@Override
public void registerKeyBindings(KeyBindingRegistry registry) {
@@ -282,13 +328,17 @@ public class ReplayMod implements Module {
//$$ FML_BUS.register(this); // For runLater(Runnable)
//#endif
FML_BUS.register(keyBindingRegistry);
FORGE_BUS.register(backgroundProcesses);
backgroundProcesses.register();
keyBindingRegistry.register();
// 1.7.10 crashes when render distance > 16
//#if MC>=10800
if (!MCVer.hasOptifine()) {
//#if MC>=11400
//$$ GameOption.RENDER_DISTANCE.setMax(64f);
//#else
GameSettings.Options.RENDER_DISTANCE.setValueMax(64f);
//#endif
}
//#endif
@@ -334,8 +384,32 @@ public class ReplayMod implements Module {
* processed, otherwise a livelock may occur.
*/
private boolean inRunLater = false;
//#if MC>=11400
//$$ private boolean inRenderTaskQueue = false;
//#endif
public void runLater(Runnable runnable) {
//#if MC>=11400
//$$ if (mc.isOnThread() && inRunLater && !inRenderTaskQueue) {
//$$ ((MinecraftAccessor) mc).getRenderTaskQueue().offer(() -> {
//$$ inRenderTaskQueue = true;
//$$ try {
//$$ runLater(runnable);
//$$ } finally {
//$$ inRenderTaskQueue = false;
//$$ }
//$$ });
//$$ } else {
//$$ mc.method_18858(() -> {
//$$ inRunLater = true;
//$$ try {
//$$ runnable.run();
//$$ } finally {
//$$ inRunLater = false;
//$$ }
//$$ });
//$$ }
//#else
if (mc.isCallingFromMinecraftThread() && inRunLater) {
//#if MC>=10800
FORGE_BUS.register(new Object() {
@@ -369,6 +443,7 @@ public class ReplayMod implements Module {
}
}, null));
}
//#endif
}
//#if MC<=10710
@@ -403,10 +478,16 @@ public class ReplayMod implements Module {
//#endif
public String getVersion() {
//#if MC>=11300
return getContainer().getModInfo().getVersion().toString();
//#if MC>=11400
//$$ return FabricLoader.getInstance().getModContainer(MOD_ID)
//$$ .orElseThrow(IllegalStateException::new)
//$$ .getMetadata().getVersion().toString();
//#else
//$$ return getContainer().getVersion();
//#if MC>=11300
return ModList.get().getModContainerById(MOD_ID).get().getModInfo().getVersion().toString();
//#else
//$$ return Loader.instance().getIndexedModList().get(MOD_ID).getVersion();
//#endif
//#endif
}

View File

@@ -1,12 +1,23 @@
package com.replaymod.core;
import com.replaymod.core.events.SettingsChangedEvent;
import com.replaymod.core.events.SettingsChangedCallback;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
//#if MC>=11400
//$$ import com.google.gson.Gson;
//$$ import com.google.gson.GsonBuilder;
//$$ import com.google.gson.JsonElement;
//$$ import com.google.gson.JsonObject;
//$$ import com.google.gson.JsonPrimitive;
//$$ import java.io.IOException;
//$$ import java.nio.charset.StandardCharsets;
//$$ import java.nio.file.Files;
//$$ import java.nio.file.Path;
//#else
//#if MC>=11300
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.fml.ModLoadingContext;
@@ -15,19 +26,63 @@ import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
//#else
//$$ import net.minecraftforge.common.config.Configuration;
//#endif
//#endif
import static com.replaymod.core.versions.MCVer.*;
public class SettingsRegistry {
private static final Object NULL_OBJECT = new Object();
private Map<SettingKey<?>, Object> settings = new ConcurrentHashMap<>();
//#if MC>=11400
//$$ private final Path configFile = getMinecraft().runDirectory.toPath().resolve("configs/replaymod.json");
//#else
private static final Object NULL_OBJECT = new Object();
//#if MC>=11300
private ForgeConfigSpec spec;
private ModConfig config;
//#else
//$$ private Configuration configuration;
//#endif
//#endif
//#if MC>=11400
//$$ public void register() {
//$$ String config;
//$$ if (Files.exists(configFile)) {
//$$ try {
//$$ config = new String(Files.readAllBytes(configFile), StandardCharsets.UTF_8);
//$$ } catch (IOException e) {
//$$ e.printStackTrace();
//$$ return;
//$$ }
//$$ } else {
//$$ save();
//$$ return;
//$$ }
//$$ Gson gson = new Gson();
//$$ JsonObject root = gson.fromJson(config, JsonObject.class);
//$$ for (Map.Entry<SettingKey<?>, Object> entry : settings.entrySet()) {
//$$ SettingKey<?> key = entry.getKey();
//$$ JsonElement category = root.get(key.getCategory());
//$$ if (category != null && category.isJsonObject()) {
//$$ JsonElement valueElem = category.getAsJsonObject().get(key.getKey());
//$$ if (!valueElem.isJsonPrimitive()) continue;
//$$ JsonPrimitive value = valueElem.getAsJsonPrimitive();
//$$ if (key.getDefault() instanceof Boolean && value.isBoolean()) {
//$$ entry.setValue(value.getAsBoolean());
//$$ }
//$$ if (key.getDefault() instanceof Integer && value.isNumber()) {
//$$ entry.setValue(value.getAsNumber().intValue());
//$$ }
//$$ if (key.getDefault() instanceof Double && value.isNumber()) {
//$$ entry.setValue(value.getAsNumber().doubleValue());
//$$ }
//$$ if (key.getDefault() instanceof String && value.isString()) {
//$$ entry.setValue(value.getAsString());
//$$ }
//$$ }
//$$ }
//$$ }
//#else
//#if MC>=11300
public void register() {
if (spec == null) {
@@ -62,6 +117,7 @@ public class SettingsRegistry {
//$$ }
//$$ }
//#endif
//#endif
public void register(Class<?> settingsClass) {
for (Field field : settingsClass.getDeclaredFields()) {
@@ -77,6 +133,9 @@ public class SettingsRegistry {
}
public void register(SettingKey<?> key) {
//#if MC>=11400
//$$ settings.put(key, key.getDefault());
//#else
//#if MC>=11300
if (spec != null) {
throw new IllegalStateException("Cannot register more settings are spec has been built.");
@@ -101,6 +160,7 @@ public class SettingsRegistry {
//$$ }
//$$ settings.put(key, value);
//#endif
//#endif
}
public Set<SettingKey<?>> getSettings() {
@@ -116,6 +176,7 @@ public class SettingsRegistry {
}
public <T> void set(SettingKey<T> key, T value) {
//#if MC<11400
//#if MC>=11300
if (config != null) {
config.getConfigData().set(key.getCategory() + "." + key.getKey(), value);
@@ -133,11 +194,42 @@ public class SettingsRegistry {
//$$ throw new IllegalArgumentException("Default type " + key.getDefault().getClass() + " not supported.");
//$$ }
//#endif
//#endif
settings.put(key, value);
FML_BUS.post(new SettingsChangedEvent(this, key));
SettingsChangedCallback.EVENT.invoker().onSettingsChanged(this, key);
}
public void save() {
//#if MC>=11400
//$$ JsonObject root = new JsonObject();
//$$ for (Map.Entry<SettingKey<?>, Object> entry : settings.entrySet()) {
//$$ SettingKey<?> key = entry.getKey();
//$$ JsonObject category = root.getAsJsonObject(key.getCategory());
//$$ if (category == null) {
//$$ category = new JsonObject();
//$$ root.add(key.getCategory(), category);
//$$ }
//$$
//$$ Object value = entry.getValue();
//$$ if (value instanceof Boolean) {
//$$ category.addProperty(key.getKey(), (Boolean) value);
//$$ }
//$$ if (value instanceof Number) {
//$$ category.addProperty(key.getKey(), (Number) value);
//$$ }
//$$ if (value instanceof String) {
//$$ category.addProperty(key.getKey(), (String) value);
//$$ }
//$$ }
//$$ Gson gson = new GsonBuilder().setPrettyPrinting().create();
//$$ String config = gson.toJson(gson);
//$$ try {
//$$ Files.createDirectories(configFile.getParent());
//$$ Files.write(configFile, config.getBytes(StandardCharsets.UTF_8));
//$$ } catch (IOException e) {
//$$ e.printStackTrace();
//$$ }
//#else
//#if MC>=11300
if (config != null) {
config.save();
@@ -145,6 +237,7 @@ public class SettingsRegistry {
//#else
//$$ configuration.save();
//#endif
//#endif
}
public interface SettingKey<T> {

View File

@@ -0,0 +1,19 @@
//#if MC>=11300
package com.replaymod.core.events;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public interface KeyBindingEventCallback {
Event<KeyBindingEventCallback> EVENT = EventFactory.createArrayBacked(
KeyBindingEventCallback.class,
(listeners) -> () -> {
for (KeyBindingEventCallback listener : listeners) {
listener.onKeybindingEvent();
}
}
);
void onKeybindingEvent();
}
//#endif

View File

@@ -0,0 +1,19 @@
//#if MC>=11300
package com.replaymod.core.events;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public interface KeyEventCallback {
Event<KeyEventCallback> EVENT = EventFactory.createArrayBacked(
KeyEventCallback.class,
(listeners) -> (key, scanCode, action, modifiers) -> {
for (KeyEventCallback listener : listeners) {
listener.onKeyEvent(key, scanCode, action, modifiers);
}
}
);
void onKeyEvent(int key, int scanCode, int action, int modifiers);
}
//#endif

View File

@@ -0,0 +1,19 @@
//#if MC>=11300
package com.replaymod.core.events;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public interface PostRenderCallback {
Event<PostRenderCallback> EVENT = EventFactory.createArrayBacked(
PostRenderCallback.class,
(listeners) -> () -> {
for (PostRenderCallback listener : listeners) {
listener.postRender();
}
}
);
void postRender();
}
//#endif

View File

@@ -0,0 +1,19 @@
//#if MC>=11400
//$$ package com.replaymod.core.events;
//$$
//$$ import net.fabricmc.fabric.api.event.Event;
//$$ import net.fabricmc.fabric.api.event.EventFactory;
//$$
//$$ public interface PostRenderWorldCallback {
//$$ Event<PostRenderWorldCallback> EVENT = EventFactory.createArrayBacked(
//$$ PostRenderWorldCallback.class,
//$$ (listeners) -> () -> {
//$$ for (PostRenderWorldCallback listener : listeners) {
//$$ listener.postRenderWorld();
//$$ }
//$$ }
//$$ );
//$$
//$$ void postRenderWorld();
//$$ }
//#endif

View File

@@ -0,0 +1,19 @@
//#if MC>=11300
package com.replaymod.core.events;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public interface PreRenderCallback {
Event<PreRenderCallback> EVENT = EventFactory.createArrayBacked(
PreRenderCallback.class,
(listeners) -> () -> {
for (PreRenderCallback listener : listeners) {
listener.preRender();
}
}
);
void preRender();
}
//#endif

View File

@@ -0,0 +1,22 @@
//#if MC>=11300
package com.replaymod.core.events;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public interface PreRenderHandCallback {
Event<PreRenderHandCallback> EVENT = EventFactory.createArrayBacked(
PreRenderHandCallback.class,
(listeners) -> () -> {
for (PreRenderHandCallback listener : listeners) {
if (listener.preRenderHand()) {
return true;
}
}
return false;
}
);
boolean preRenderHand();
}
//#endif

View File

@@ -0,0 +1,18 @@
package com.replaymod.core.events;
import com.replaymod.core.SettingsRegistry;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public interface SettingsChangedCallback {
Event<SettingsChangedCallback> EVENT = EventFactory.createArrayBacked(
SettingsChangedCallback.class,
(listeners) -> (registry, key) -> {
for (SettingsChangedCallback listener : listeners) {
listener.onSettingsChanged(registry, key);
}
}
);
void onSettingsChanged(SettingsRegistry registry, SettingsRegistry.SettingKey<?> key);
}

View File

@@ -1,24 +0,0 @@
package com.replaymod.core.events;
import com.replaymod.core.SettingsRegistry;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
//#if MC>=10800
//#if MC>=11300
import net.minecraftforge.eventbus.api.Event;
//#else
//$$ import net.minecraftforge.fml.common.eventhandler.Event;
//#endif
//#else
//$$ import cpw.mods.fml.common.eventhandler.Event;
//#endif
@RequiredArgsConstructor
public class SettingsChangedEvent extends Event {
@Getter
private final SettingsRegistry settingsRegistry;
@Getter
private final SettingsRegistry.SettingKey<?> key;
}

View File

@@ -9,40 +9,36 @@ import de.johni0702.minecraft.gui.container.VanillaGuiScreen;
import de.johni0702.minecraft.gui.element.GuiElement;
import de.johni0702.minecraft.gui.layout.CustomLayout;
import de.johni0702.minecraft.gui.layout.VerticalLayout;
import de.johni0702.minecraft.gui.utils.EventRegistrations;
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
//#if MC>=11400
//$$ import de.johni0702.minecraft.gui.versions.callbacks.InitScreenCallback;
//$$ import net.minecraft.client.gui.Screen;
//#else
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge;
//#if MC>=10800
//#if MC>=11300
import net.minecraftforge.eventbus.api.SubscribeEvent;
//#else
//$$ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
//#endif
//#else
//$$ import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import static com.replaymod.core.versions.MCVer.getGui;
//#endif
import static com.replaymod.core.versions.MCVer.getGui;
import static com.replaymod.core.versions.MCVer.getMinecraft;
public class GuiBackgroundProcesses {
public class GuiBackgroundProcesses extends EventRegistrations {
private GuiPanel panel = new GuiPanel().setLayout(new VerticalLayout().setSpacing(10));
public void register() {
MinecraftForge.EVENT_BUS.register(this);
}
public void unregister() {
MinecraftForge.EVENT_BUS.unregister(this);
}
//#if MC>=11400
//$$ { on(InitScreenCallback.EVENT, (screen, buttons) -> onGuiInit(screen)); }
//$$ private void onGuiInit(Screen guiScreen) {
//#else
@SubscribeEvent
public void onGuiInit(GuiScreenEvent.InitGuiEvent.Post event) {
if (getGui(event) != getMinecraft().currentScreen) return; // people tend to construct GuiScreens without opening them
net.minecraft.client.gui.GuiScreen guiScreen = getGui(event);
//#endif
if (guiScreen != getMinecraft().currentScreen) return; // people tend to construct GuiScreens without opening them
VanillaGuiScreen.setup(getGui(event)).setLayout(new CustomLayout<GuiScreen>() {
VanillaGuiScreen.setup(guiScreen).setLayout(new CustomLayout<GuiScreen>() {
@Override
protected void layout(GuiScreen container, int width, int height) {
pos(panel, width - 5 - width(panel), 5);

View File

@@ -1,3 +1,4 @@
//#if MC<11400
package com.replaymod.core.gui;
import com.replaymod.core.ReplayMod;
@@ -59,3 +60,4 @@ public class GuiFactory implements IModGuiFactory {
return null;
}
}
//#endif

View File

@@ -1,35 +1,50 @@
package com.replaymod.core.handler;
import com.replaymod.core.mixin.GuiMainMenuAccessor;
import de.johni0702.minecraft.gui.utils.EventRegistrations;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiScreenRealmsProxy;
import org.lwjgl.opengl.GL11;
import java.util.List;
import static com.replaymod.core.versions.MCVer.*;
//#if MC>=11400
//$$ import de.johni0702.minecraft.gui.versions.callbacks.InitScreenCallback;
//$$ import net.minecraft.client.gui.widget.AbstractButtonWidget;
//#else
import net.minecraft.client.gui.GuiButton;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import org.lwjgl.opengl.GL11;
import static com.replaymod.core.versions.MCVer.*;
//#endif
/**
* Moves certain buttons on the main menu upwards so we can inject our own.
*/
public class MainMenuHandler {
public void register() {
MinecraftForge.EVENT_BUS.register(this);
}
public class MainMenuHandler extends EventRegistrations {
//#if MC>=11400
//$$ { on(InitScreenCallback.EVENT, this::onInit); }
//$$ public void onInit(Screen guiScreen, List<AbstractButtonWidget> buttonList) {
//#else
@SubscribeEvent
public void onInit(GuiScreenEvent.InitGuiEvent.Post event) {
GuiScreen guiScreen = getGui(event);
List<GuiButton> buttonList = getButtonList(event);
//#endif
if (guiScreen instanceof GuiMainMenu) {
GuiMainMenu gui = (GuiMainMenu) guiScreen;
int realmsOffset = 0;
for (GuiButton button : getButtonList(event)) {
//#if MC>=11400
//$$ for (AbstractButtonWidget button : buttonList) {
//#else
for (GuiButton button : buttonList) {
//#endif
// Buttons that aren't in a rectangle directly above our space don't need moving
if (button.x + button.width < gui.width / 2 - 100
if (button.x + width(button) < gui.width / 2 - 100
|| button.x > gui.width / 2 + 100
|| button.y > gui.height / 4 + 10 + 4 * 24) continue;
// Move button up to make space for one rows of buttons
@@ -37,11 +52,15 @@ public class MainMenuHandler {
int offset = -1 * 24 + 10;
button.y += offset;
//#if MC>=11400
//$$ // FIXME looks like the button has moved into the realms lib?
//#else
//#if MC>=11300
if (button.id == 14) {
realmsOffset = offset;
}
//#endif
//#endif
}
//#if MC>=11300
GuiMainMenuAccessor guiA = (GuiMainMenuAccessor) gui;
@@ -58,6 +77,9 @@ public class MainMenuHandler {
private final int offset;
private RealmsNotificationProxy(GuiScreenRealmsProxy proxy, int offset) {
//#if MC>=11400
//$$ super(null);
//#endif
this.proxy = proxy;
this.offset = offset;
}

View File

@@ -0,0 +1,13 @@
//#if MC>=11400
//$$ package com.replaymod.core.mixin;
//$$
//$$ import net.minecraft.client.gui.widget.AbstractButtonWidget;
//$$ import org.spongepowered.asm.mixin.Mixin;
//$$ import org.spongepowered.asm.mixin.gen.Accessor;
//$$
//$$ @Mixin(AbstractButtonWidget.class)
//$$ public interface AbstractButtonWidgetAccessor {
//$$ @Accessor
//$$ int getHeight();
//$$ }
//#endif

View File

@@ -0,0 +1,32 @@
package com.replaymod.core.mixin;
import net.minecraft.client.gui.GuiScreen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
//#if MC>=11400
//$$ import net.minecraft.client.gui.widget.AbstractButtonWidget;
//#else
import net.minecraft.client.gui.GuiButton;
//#endif
//#if MC>=11300
import net.minecraft.client.gui.IGuiEventListener;
//#endif
@Mixin(GuiScreen.class)
public interface GuiScreenAccessor {
@Accessor
//#if MC>=11400
//$$ List<AbstractButtonWidget> getButtons();
//#else
List<GuiButton> getButtons();
//#endif
//#if MC>=11300
@Accessor
List<IGuiEventListener> getChildren();
//#endif
}

View File

@@ -7,7 +7,10 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.Queue;
//#if MC<11400
import java.util.concurrent.FutureTask;
//#endif
@Mixin(Minecraft.class)
public interface MinecraftAccessor {
@@ -16,8 +19,13 @@ public interface MinecraftAccessor {
@Accessor
void setTimer(Timer value);
//#if MC>=11400
//$$ @Accessor
//$$ Queue<Runnable> getRenderTaskQueue();
//#else
@Accessor
Queue<FutureTask<?>> getScheduledTasks();
//#endif
@Accessor("hasCrashed")
boolean hasCrashed();

View File

@@ -0,0 +1,59 @@
//#if MC>=11400
//$$ package com.replaymod.core.mixin;
//$$
//$$ import com.replaymod.core.events.PostRenderWorldCallback;
//$$ import com.replaymod.core.events.PreRenderHandCallback;
//$$ import de.johni0702.minecraft.gui.versions.callbacks.PostRenderHudCallback;
//$$ import de.johni0702.minecraft.gui.versions.callbacks.PostRenderScreenCallback;
//$$ import net.minecraft.client.render.Camera;
//$$ import net.minecraft.client.render.GameRenderer;
//$$ import org.spongepowered.asm.mixin.Mixin;
//$$ import org.spongepowered.asm.mixin.injection.At;
//$$ import org.spongepowered.asm.mixin.injection.Inject;
//$$ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//$$
//$$ @Mixin(GameRenderer.class)
//$$ public class MixinGameRenderer {
//$$ @Inject(
//$$ method = "render",
//$$ at = @At(
//$$ value = "INVOKE",
//$$ target = "Lnet/minecraft/client/gui/hud/InGameHud;draw(F)V",
//$$ shift = At.Shift.AFTER
//$$ )
//$$ )
//$$ private void postRenderOverlay(float partialTicks, long nanoTime, boolean renderWorld, CallbackInfo ci) {
//$$ PostRenderHudCallback.EVENT.invoker().postRenderHud(partialTicks);
//$$ }
//$$
//$$ @Inject(
//$$ method = "render",
//$$ at = @At(
//$$ value = "INVOKE",
//$$ target = "Lnet/minecraft/client/gui/Screen;render(IIF)V",
//$$ shift = At.Shift.AFTER
//$$ )
//$$ )
//$$ private void postRenderScreen(float partialTicks, long nanoTime, boolean renderWorld, CallbackInfo ci) {
//$$ PostRenderScreenCallback.EVENT.invoker().postRenderScreen(partialTicks);
//$$ }
//$$
//$$ @Inject(
//$$ method = "renderCenter",
//$$ at = @At(
//$$ value = "FIELD",
//$$ target = "Lnet/minecraft/client/render/GameRenderer;renderHand:Z"
//$$ )
//$$ )
//$$ private void postRenderWorld(float partialTicks, long nanoTime, CallbackInfo ci) {
//$$ PostRenderWorldCallback.EVENT.invoker().postRenderWorld();
//$$ }
//$$
//$$ @Inject(method = "renderHand", at = @At("HEAD"), cancellable = true)
//$$ private void preRenderHand(Camera camera, float partialTicks, CallbackInfo ci) {
//$$ if (PreRenderHandCallback.EVENT.invoker().preRenderHand()) {
//$$ ci.cancel();
//$$ }
//$$ }
//$$ }
//#endif

View File

@@ -0,0 +1,61 @@
//#if MC>=11300
package com.replaymod.core.mixin;
import com.replaymod.core.events.KeyBindingEventCallback;
import com.replaymod.core.events.KeyEventCallback;
import net.minecraft.client.KeyboardListener;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(KeyboardListener.class)
public class MixinKeyboardListener {
@Inject(method = "onKeyEvent", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/settings/KeyBinding;onTick(Lnet/minecraft/client/util/InputMappings$Input;)V", shift = At.Shift.AFTER))
private void afterKeyBindingTick(long windowPointer, int key, int scanCode, int action, int modifiers, CallbackInfo ci) {
KeyBindingEventCallback.EVENT.invoker().onKeybindingEvent();
KeyEventCallback.EVENT.invoker().onKeyEvent(key, scanCode, action, modifiers);
}
//#if MC>=11400
//$$ /* FIXME we currently don't use these but they also don't work since their target is wrapped in a lambda,
//$$ see MixinMouseListener for working examples
//$$ @Redirect(
//$$ method = "onKey",
//$$ at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/ParentElement;keyPressed(III)Z")
//$$ )
//$$ private boolean keyPressed(ParentElement element, int keyCode, int modifiers, int scanCode) {
//$$ if (KeyboardCallback.EVENT.invoker().keyPressed(keyCode, modifiers, scanCode)) {
//$$ return true;
//$$ } else {
//$$ return element.keyPressed(keyCode, modifiers, scanCode);
//$$ }
//$$ }
//$$
//$$ @Redirect(
//$$ method = "onKey",
//$$ at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/ParentElement;keyReleased(III)Z")
//$$ )
//$$ private boolean keyReleased(ParentElement element, int keyCode, int modifiers, int scanCode) {
//$$ if (KeyboardCallback.EVENT.invoker().keyReleased(keyCode, modifiers, scanCode)) {
//$$ return true;
//$$ } else {
//$$ return element.keyReleased(keyCode, modifiers, scanCode);
//$$ }
//$$ }
//$$
//$$ @Redirect(
//$$ method = "onKey",
//$$ at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/ParentElement;charTyped(CI)Z")
//$$ )
//$$ private boolean charTyped(ParentElement element, char keyChar, int modifiers) {
//$$ if (KeyboardCallback.EVENT.invoker().charTyped(keyChar, modifiers)) {
//$$ return true;
//$$ } else {
//$$ return element.charTyped(keyChar, modifiers);
//$$ }
//$$ }
//$$ */
//#endif
}
//#endif

View File

@@ -1,18 +1,70 @@
//#if MC>=11300
package com.replaymod.core.mixin;
import com.replaymod.core.events.PostRenderCallback;
import com.replaymod.core.events.PreRenderCallback;
import com.replaymod.core.versions.MCVer;
import de.johni0702.minecraft.gui.versions.callbacks.OpenGuiScreenCallback;
import de.johni0702.minecraft.gui.versions.callbacks.PreTickCallback;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//#if MC>=11400
//$$ import net.minecraft.util.NonBlockingThreadExecutor;
//#endif
@Mixin(Minecraft.class)
public abstract class MixinMinecraft implements MCVer.MinecraftMethodAccessor {
public abstract class MixinMinecraft
//#if MC>=11400
//$$ extends NonBlockingThreadExecutor<Runnable>
//#endif
implements MCVer.MinecraftMethodAccessor {
//#if MC>=11400
//$$ public MixinMinecraft(String string_1) { super(string_1); }
//#endif
@Shadow protected abstract void processKeyBinds();
@Override
public void replayModProcessKeyBinds() {
processKeyBinds();
}
//#if MC>=11400
//$$ @Override
//$$ public void replayModExecuteTaskQueue() {
//$$ executeTaskQueue();
//$$ }
//#endif
@Inject(method = "runGameLoop",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/renderer/GameRenderer;updateCameraAndRender(FJZ)V"))
private void preRender(boolean unused, CallbackInfo ci) {
PreRenderCallback.EVENT.invoker().preRender();
}
@Inject(method = "runGameLoop",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/renderer/GameRenderer;updateCameraAndRender(FJZ)V",
shift = At.Shift.AFTER))
private void postRender(boolean unused, CallbackInfo ci) {
PostRenderCallback.EVENT.invoker().postRender();
}
@Inject(method = "runTick", at = @At("HEAD"))
private void preTick(CallbackInfo ci) {
PreTickCallback.EVENT.invoker().preTick();
}
@Inject(method = "displayGuiScreen", at = @At(value = "FIELD", target = "Lnet/minecraft/client/Minecraft;currentScreen:Lnet/minecraft/client/gui/GuiScreen;"))
private void openGuiScreen(GuiScreen newGuiScreen, CallbackInfo ci) {
OpenGuiScreenCallback.EVENT.invoker().openGuiScreen(newGuiScreen);
}
}
//#endif

View File

@@ -0,0 +1,37 @@
//#if MC>=11400
//$$ package com.replaymod.core.mixin;
//$$
//$$ import com.replaymod.core.ReplayMod;
//$$ import com.replaymod.core.versions.LangResourcePack;
//$$ import net.fabricmc.fabric.api.resource.ModResourcePack;
//$$ import net.fabricmc.fabric.impl.resources.ModResourcePackUtil;
//$$ import net.fabricmc.loader.api.FabricLoader;
//$$ import net.fabricmc.loader.api.ModContainer;
//$$ import net.minecraft.resource.ResourcePack;
//$$ import net.minecraft.resource.ResourceType;
//$$ import org.spongepowered.asm.mixin.Mixin;
//$$ import org.spongepowered.asm.mixin.injection.At;
//$$ import org.spongepowered.asm.mixin.injection.Inject;
//$$ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//$$
//$$ import java.util.List;
//$$
//$$ @Mixin(value = ModResourcePackUtil.class, remap = false)
//$$ public class MixinModResourcePackUtil {
//$$ @Inject(method = "appendModResourcePacks", at = @At("RETURN"), remap = false)
//$$ private static void injectRMLangPack(List<ResourcePack> packList, ResourceType type, CallbackInfo ci) {
//$$ if (type != ResourceType.ASSETS) return;
//$$
//$$ for (int i = 0; i < packList.size(); i++) {
//$$ ResourcePack pack = packList.get(i);
//$$ if (pack instanceof ModResourcePack && ((ModResourcePack) pack).getFabricModMetadata().getId().equals(ReplayMod.MOD_ID)) {
//$$ ModContainer container = FabricLoader.getInstance().getModContainer(ReplayMod.MOD_ID).orElseThrow(IllegalAccessError::new);
//$$ packList.add(i, new LangResourcePack(container.getRootPath()));
//$$ return;
//$$ }
//$$ }
//$$
//$$ throw new IllegalStateException("Could not find ReplayMod resource pack.");
//$$ }
//$$ }
//#endif

View File

@@ -0,0 +1,60 @@
//#if MC>=11400
//$$ package com.replaymod.core.mixin;
//$$
//$$ import com.replaymod.core.events.KeyBindingEventCallback;
//$$ import de.johni0702.minecraft.gui.versions.callbacks.MouseCallback;
//$$ import net.minecraft.client.Mouse;
//$$ import net.minecraft.client.gui.Element;
//$$ import net.minecraft.client.gui.ParentElement;
//$$ import org.spongepowered.asm.mixin.Mixin;
//$$ import org.spongepowered.asm.mixin.Shadow;
//$$ import org.spongepowered.asm.mixin.injection.At;
//$$ import org.spongepowered.asm.mixin.injection.Inject;
//$$ import org.spongepowered.asm.mixin.injection.Redirect;
//$$ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//$$
//$$ @Mixin(Mouse.class)
//$$ public class MixinMouseListener {
//$$ @Shadow private int activeButton;
//$$
//$$ @Inject(method = "onMouseButton", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/options/KeyBinding;onKeyPressed(Lnet/minecraft/client/util/InputUtil$KeyCode;)V", shift = At.Shift.AFTER))
//$$ private void afterKeyBindingTick(CallbackInfo ci) {
//$$ KeyBindingEventCallback.EVENT.invoker().onKeybindingEvent();
//$$ }
//$$
//$$ @Inject(method = "method_1611", at = @At("HEAD"), cancellable = true)
//$$ private void mouseDown(boolean[] result, double x, double y, int button, CallbackInfo ci) {
//$$ if (MouseCallback.EVENT.invoker().mouseDown(x, y, button)) {
//$$ result[0] = true;
//$$ ci.cancel();
//$$ }
//$$ }
//$$
//$$ @Inject(method = "method_1605", at = @At("HEAD"), cancellable = true)
//$$ private void mouseUp(boolean[] result, double x, double y, int button, CallbackInfo ci) {
//$$ if (MouseCallback.EVENT.invoker().mouseUp(x, y, button)) {
//$$ result[0] = true;
//$$ ci.cancel();
//$$ }
//$$ }
//$$
//$$ @Inject(method = "method_1602", at = @At("HEAD"), cancellable = true)
//$$ private void mouseDrag(Element element, double x, double y, double dx, double dy, CallbackInfo ci) {
//$$ if (MouseCallback.EVENT.invoker().mouseDrag(x, y, this.activeButton, dx, dy)) {
//$$ ci.cancel();
//$$ }
//$$ }
//$$
//$$ @Redirect(
//$$ method = "onMouseScroll",
//$$ at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/ParentElement;mouseScrolled(DDD)Z")
//$$ )
//$$ private boolean mouseScroll(ParentElement element, double x, double y, double scroll) {
//$$ if (MouseCallback.EVENT.invoker().mouseScroll(x, y, scroll)) {
//$$ return true;
//$$ } else {
//$$ return element.mouseScrolled(x, y, scroll);
//$$ }
//$$ }
//$$ }
//#endif

View File

@@ -0,0 +1,27 @@
//#if MC>=11400
//$$ package com.replaymod.core.mixin;
//$$
//$$ import de.johni0702.minecraft.gui.versions.callbacks.InitScreenCallback;
//$$ import net.minecraft.client.MinecraftClient;
//$$ import net.minecraft.client.gui.Screen;
//$$ import net.minecraft.client.gui.widget.AbstractButtonWidget;
//$$ import org.spongepowered.asm.mixin.Final;
//$$ import org.spongepowered.asm.mixin.Mixin;
//$$ import org.spongepowered.asm.mixin.Shadow;
//$$ import org.spongepowered.asm.mixin.injection.At;
//$$ import org.spongepowered.asm.mixin.injection.Inject;
//$$ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
//$$
//$$ import java.util.List;
//$$
//$$ @Mixin(Screen.class)
//$$ public class MixinScreen {
//$$ @Shadow
//$$ protected @Final List<AbstractButtonWidget> buttons;
//$$
//$$ @Inject(method = "init(Lnet/minecraft/client/MinecraftClient;II)V", at = @At("RETURN"))
//$$ private void init(MinecraftClient minecraftClient_1, int int_1, int int_2, CallbackInfo ci) {
//$$ InitScreenCallback.EVENT.invoker().initScreen((Screen) (Object) this, buttons);
//$$ }
//$$ }
//#endif

View File

@@ -1,64 +0,0 @@
package com.replaymod.core.utils;
import com.replaymod.replaystudio.us.myles.ViaVersion.util.ReflectionUtil;
import net.fabricmc.fabric.api.event.Event;
import java.lang.reflect.InvocationTargetException;
public class EventRegistration<T> {
public static <T> EventRegistration<T> create(Event<T> event, T callback) {
return new EventRegistration<>(event, callback);
}
public static <T> EventRegistration<T> register(Event<T> event, T callback) {
EventRegistration<T> registration = new EventRegistration<>(event, callback);
registration.register();
return registration;
}
private final Event<T> event;
private final T listener;
private boolean registered;
private EventRegistration(Event<T> event, T listener) {
this.event = event;
this.listener = listener;
event.register(listener);
}
public void register() {
if (registered) {
throw new IllegalStateException();
}
event.register(listener);
registered = true;
}
@SuppressWarnings("unchecked")
public void unregister() {
if (!registered) {
throw new IllegalStateException();
}
try {
T[] handlers = (T[]) ReflectionUtil.get(event, "handlers", Object[].class);
T[] copy = (T[]) new Object[handlers.length - 1];
for (int from = 0, to = 0; from < handlers.length; from++) {
if (handlers[from] == listener) {
continue;
}
copy[to++] = handlers[from];
}
if (copy.length == 0) {
copy = null;
}
ReflectionUtil.set(event, "handlers", copy);
ReflectionUtil.invoke(event, "update");
} catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
throw new RuntimeException(e);
}
registered = false;
}
}

View File

@@ -1,31 +0,0 @@
package com.replaymod.core.utils;
import net.fabricmc.fabric.api.event.Event;
import java.util.ArrayList;
import java.util.List;
public class EventRegistrations {
private List<EventRegistration<?>> registrations = new ArrayList<>();
public <T> EventRegistrations on(EventRegistration<T> registration) {
registrations.add(registration);
return this;
}
public <T> EventRegistrations on(Event<T> event, T listener) {
return on(EventRegistration.create(event, listener));
}
public void register() {
for (EventRegistration<?> registration : registrations) {
registration.register();
}
}
public void unregister() {
for (EventRegistration<?> registration : registrations) {
registration.unregister();
}
}
}

View File

@@ -2,6 +2,12 @@ package com.replaymod.core.utils;
import com.replaymod.replaystudio.data.ModInfo;
import net.minecraft.util.ResourceLocation;
//#if MC>=11400
//$$ import net.fabricmc.loader.api.FabricLoader;
//$$ import net.fabricmc.loader.api.ModContainer;
//$$ import net.minecraft.util.registry.Registry;
//#else
//#if MC>=11200
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.RegistryManager;
@@ -25,6 +31,7 @@ import net.minecraftforge.fml.ModList;
//$$ import cpw.mods.fml.common.Loader;
//$$ import cpw.mods.fml.common.ModContainer;
//#endif
//#endif
import java.util.*;
import java.util.function.Function;
@@ -34,12 +41,21 @@ public class ModCompat {
@SuppressWarnings("unchecked")
public static Collection<ModInfo> getInstalledNetworkMods() {
//#if MC>=11300
//#if MC>=11400
//$$ Map<String, ModInfo> modInfoMap = FabricLoader.getInstance().getAllMods().stream()
//$$ .map(ModContainer::getMetadata)
//$$ .map(m -> new ModInfo(m.getId(), m.getName(), m.getVersion().toString()))
//$$ .collect(Collectors.toMap(ModInfo::getId, Function.identity()));
//$$ return Registry.REGISTRIES.stream()
//$$ .map(Registry::getIds).flatMap(Set::stream)
//#else
Map<String, ModInfo> modInfoMap = ModList.get().getMods().stream()
.map(m -> new ModInfo(m.getModId(), m.getDisplayName(), m.getVersion().toString()))
.collect(Collectors.toMap(ModInfo::getId, Function.identity()));
return RegistryManager.ACTIVE.takeSnapshot(false).keySet().stream()
.map(RegistryManager.ACTIVE::getRegistry)
.map(ForgeRegistry::getKeys).flatMap(Set::stream)
//#endif
.map(ResourceLocation::getNamespace).filter(s -> !s.equals("minecraft")).distinct()
.map(modInfoMap::get).filter(Objects::nonNull)
.collect(Collectors.toList());

View File

@@ -4,22 +4,15 @@ package com.replaymod.core.versions;
import com.google.gson.Gson;
import com.replaymod.core.ReplayMod;
import net.minecraft.resources.AbstractResourcePack;
import net.minecraft.resources.IPackFinder;
import net.minecraft.resources.IResourcePack;
import net.minecraft.resources.ResourcePackFileNotFoundException;
import net.minecraft.resources.ResourcePackInfo;
import net.minecraft.resources.ResourcePackType;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.packs.ModFileResourcePack;
import net.minecraftforge.fml.packs.ResourcePackLoader;
import org.apache.commons.io.IOUtils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringBufferInputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -33,8 +26,18 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
//#if MC>=11400
//#else
import net.minecraft.resources.IPackFinder;
import net.minecraft.resources.ResourcePackInfo;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.packs.ModFileResourcePack;
import net.minecraftforge.fml.packs.ResourcePackLoader;
//#endif
/**
* Resource pack which on-the-fly converts pre-1.13 language files into 1.13 json format.
* Also remaps `replaymod.input.*` bindings to `key.replaymod.*` as convention on Fabric.
*/
public class LangResourcePack extends AbstractResourcePack {
private static final Gson GSON = new Gson();
@@ -42,13 +45,24 @@ public class LangResourcePack extends AbstractResourcePack {
private static final Pattern JSON_FILE_PATTERN = Pattern.compile("^assets/" + ReplayMod.MOD_ID + "/lang/([a-z][a-z])_([a-z][a-z]).json$");
private static final Pattern LANG_FILE_NAME_PATTERN = Pattern.compile("^([a-z][a-z])_([a-z][a-z]).lang$");
LangResourcePack() {
//#if MC>=11400
//$$ public static final String LEGACY_KEY_PREFIX = "replaymod.input.";
//$$ private static final String FABRIC_KEY_FORMAT = "key." + ReplayMod.MOD_ID + ".%s";
//$$
//$$ private final Path basePath;
//$$ public LangResourcePack(Path basePath) {
//$$ super(new File(NAME));
//$$ this.basePath = basePath;
//$$ }
//#else
public LangResourcePack() {
super(new File(NAME));
}
private ModFileResourcePack getParent() {
return ResourcePackLoader.getResourcePackFor(ReplayMod.MOD_ID).orElseThrow(() -> new RuntimeException("Failed to get ReplayMod resource pack!"));
}
//#endif
private String langName(String path) {
Matcher matcher = JSON_FILE_PATTERN.matcher(path);
@@ -56,14 +70,27 @@ public class LangResourcePack extends AbstractResourcePack {
return String.format("%s_%s.lang", matcher.group(1), matcher.group(2).toUpperCase());
}
private Path langPath(String path) {
//#if MC>=11400
//$$ private Path baseLangPath() {
//$$ return basePath.resolve("assets").resolve(ReplayMod.MOD_ID).resolve("lang");
//$$ }
//#else
private Path baseLangPath() {
ModFileResourcePack parent = getParent();
if (parent == null) return null;
ModFile modFile = parent.getModFile();
return modFile.getLocator().findPath(modFile, "assets", ReplayMod.MOD_ID, "lang");
}
//#endif
private Path langPath(String path) {
String langName = langName(path);
if (langName == null) return null;
return modFile.getLocator().findPath(modFile, "assets", ReplayMod.MOD_ID, "lang", langName);
Path basePath = baseLangPath();
//#if MC<11400
if (basePath == null) return null;
//#endif
return basePath.resolve(langName);
}
private String convertValue(String value) {
@@ -73,11 +100,11 @@ public class LangResourcePack extends AbstractResourcePack {
@Override
protected InputStream getInputStream(String path) throws IOException {
if ("pack.mcmeta".equals(path)) {
return new StringBufferInputStream("{\"pack\": {\"description\": \"ReplayMod language files\", \"pack_format\": 4}}");
return new ByteArrayInputStream("{\"pack\": {\"description\": \"ReplayMod language files\", \"pack_format\": 4}}".getBytes(StandardCharsets.UTF_8));
}
Path langPath = langPath(path);
if (langPath == null) throw new ResourcePackFileNotFoundException(file, path);
if (langPath == null) throw new ResourcePackFileNotFoundException(this.file, path);
String langFile;
try (InputStream in = Files.newInputStream(langPath)) {
@@ -91,6 +118,11 @@ public class LangResourcePack extends AbstractResourcePack {
String key = line.substring(0, i);
String value = line.substring(i + 1);
value = convertValue(value);
//#if MC>=11400
//$$ if (key.startsWith(LEGACY_KEY_PREFIX)) {
//$$ key = String.format(FABRIC_KEY_FORMAT, key.substring(LEGACY_KEY_PREFIX.length()));
//$$ }
//#endif
properties.put(key, value);
}
@@ -103,22 +135,29 @@ public class LangResourcePack extends AbstractResourcePack {
return langPath != null && Files.exists(langPath);
}
@Override
public Collection<ResourceLocation> getAllResourceLocations(ResourcePackType resourcePackType, String path, int maxDepth, Predicate<String> filter) {
if (resourcePackType == ResourcePackType.CLIENT_RESOURCES && "lang".equals(path)) {
IResourcePack parent = getParent();
if (parent == null) return Collections.emptyList();
return parent.getAllResourceLocations(resourcePackType, path, maxDepth, name -> {
Matcher matcher = LANG_FILE_NAME_PATTERN.matcher(name);
if (matcher.matches()) {
return filter.test(String.format("%s_%s.json", matcher.group(1), matcher.group(1)));
} else {
return false;
}
}).stream().map(resourceLocation -> {
String p = resourceLocation.getPath().substring(0, "assets/lang/xx_XX".length()) + ".json";
return new ResourceLocation(resourceLocation.getNamespace(), p);
}).collect(Collectors.toList());
Path base = baseLangPath();
//#if MC<11400
if (base == null) return Collections.emptyList();
//#endif
try {
return Files.walk(base, 1)
.skip(1)
.filter(Files::isRegularFile)
.map(Path::getFileName).map(Path::toString)
.map(LANG_FILE_NAME_PATTERN::matcher)
.filter(Matcher::matches)
.map(matcher -> String.format("%s_%s.json", matcher.group(1), matcher.group(1)))
.filter(filter::test)
.map(name -> new ResourceLocation(ReplayMod.MOD_ID, "lang/" + name))
.collect(Collectors.toList());
} catch (IOException e) {
e.printStackTrace();
return Collections.emptyList();
}
} else {
return Collections.emptyList();
}
@@ -136,11 +175,14 @@ public class LangResourcePack extends AbstractResourcePack {
@Override
public void close() {}
// Not needed on fabric, using MixinModResourcePackUtil instead.
//#if MC<11400
public static class Finder implements IPackFinder {
@Override
public <T extends ResourcePackInfo> void addPackInfosToMap(Map<String, T> packList, ResourcePackInfo.IFactory<T> factory) {
packList.put(NAME, ResourcePackInfo.func_195793_a(NAME, true, LangResourcePack::new, factory, ResourcePackInfo.Priority.BOTTOM));
}
}
//#endif
}
//#endif

View File

@@ -1,10 +1,11 @@
package com.replaymod.core.versions;
import com.google.common.util.concurrent.ListenableFuture;
import com.replaymod.core.mixin.GuiScreenAccessor;
import com.replaymod.core.mixin.MinecraftAccessor;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.entity.model.ModelBox;
@@ -12,7 +13,6 @@ import net.minecraft.client.renderer.entity.model.ModelRenderer;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
@@ -20,11 +20,22 @@ import net.minecraft.util.Util;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
//#if MC>=11400
//$$ import com.replaymod.core.mixin.AbstractButtonWidgetAccessor;
//$$ import net.minecraft.client.gui.widget.AbstractButtonWidget;
//$$ import java.util.concurrent.CompletableFuture;
//#else
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import net.minecraft.entity.EntityLivingBase;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.client.event.RenderLivingEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.IEventBus;
//#endif
//#if MC>=11300
import net.minecraft.client.MainWindow;
@@ -40,6 +51,12 @@ import org.lwjgl.glfw.GLFW;
//$$ import java.io.IOException;
//#endif
//#if MC>=10904
import com.replaymod.render.blend.mixin.ParticleAccessor;
import net.minecraft.client.particle.Particle;
import net.minecraft.util.math.Vec3d;
//#endif
//#if MC>=10809
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
//#else
@@ -60,21 +77,46 @@ import net.minecraft.world.WorldType;
//$$ import static org.lwjgl.opengl.GL11.*;
//#endif
//#if MC>=11400
//$$ import net.fabricmc.loader.api.FabricLoader;
//#else
//#if MC>=11300
import net.minecraftforge.fml.ModList;
//#else
//$$ import net.minecraftforge.fml.common.Loader;
//#endif
//#endif
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
/**
* Abstraction over things that have changed between different MC versions.
*/
public class MCVer {
//#if MC<11400
public static IEventBus FORGE_BUS = MinecraftForge.EVENT_BUS;
//#if MC>=10809
public static IEventBus FML_BUS = FORGE_BUS;
//#else
//$$ public static EventBus FML_BUS = FMLCommonHandler.instance().bus();
//#endif
//#endif
public static boolean isModLoaded(String id) {
//#if MC>=11400
//$$ return FabricLoader.getInstance().isModLoaded(id.toLowerCase());
//#else
//#if MC>=11300
return ModList.get().isLoaded(id.toLowerCase());
//#else
//$$ return Loader.isModLoaded(id);
//#endif
//#endif
}
public static void addDetail(CrashReportCategory category, String name, Callable<String> callable) {
//#if MC>=10904
@@ -88,6 +130,33 @@ public class MCVer {
//#endif
}
//#if MC>=11400
//$$ public static void width(AbstractButtonWidget button, int value) {
//$$ button.setWidth(value);
//$$ }
//$$
//$$ public static int width(AbstractButtonWidget button) {
//$$ return button.getWidth();
//$$ }
//$$
//$$ public static int height(AbstractButtonWidget button) {
//$$ return ((AbstractButtonWidgetAccessor) button).getHeight();
//$$ }
//#else
public static void width(GuiButton button, int value) {
button.width = value;
}
public static int width(GuiButton button) {
return button.width;
}
public static int height(GuiButton button) {
return button.height;
}
//#endif
//#if MC<11400
public static void addButton(GuiScreenEvent.InitGuiEvent event, GuiButton button) {
//#if MC>=11300
event.addButton(button);
@@ -136,6 +205,7 @@ public class MCVer {
//$$ return event.entity;
//#endif
}
//#endif
public static String readString(PacketBuffer buffer, int max) {
//#if MC>=11102
@@ -153,6 +223,7 @@ public class MCVer {
//#endif
}
//#if MC<11400
public static RenderGameOverlayEvent.ElementType getType(RenderGameOverlayEvent event) {
//#if MC>=10904
return event.getType();
@@ -160,6 +231,7 @@ public class MCVer {
//$$ return event.type;
//#endif
}
//#endif
//#if MC>=10800
public static WorldType WorldType_DEBUG_ALL_BLOCK_STATES
@@ -197,7 +269,7 @@ public class MCVer {
//$$ = TextureMap.locationBlocksTexture;
//#endif
public static Entity getRidingEntity(Entity ridden) {
public static Entity getRiddenEntity(Entity ridden) {
//#if MC>=10904
return ridden.getRidingEntity();
//#else
@@ -205,9 +277,12 @@ public class MCVer {
//#endif
}
@SuppressWarnings("unchecked")
public static List<Entity> loadedEntityList(World world) {
public static Iterable<Entity> loadedEntityList(WorldClient world) {
//#if MC>=11400
//$$ return world.getEntities();
//#else
return world.loadedEntityList;
//#endif
}
@SuppressWarnings("unchecked")
@@ -226,7 +301,19 @@ public class MCVer {
@SuppressWarnings("unchecked")
public static List<EntityPlayer> playerEntities(World world) {
//#if MC>=11400
//$$ return (List) world.getPlayers();
//#else
return world.playerEntities;
//#endif
}
public static boolean isOnMainThread() {
//#if MC>=11400
//$$ return getMinecraft().isOnThread();
//#else
return getMinecraft().isCallingFromMinecraftThread();
//#endif
}
//#if MC>=11300
@@ -243,7 +330,13 @@ public class MCVer {
//$$ }
//#endif
public static ListenableFuture setServerResourcePack(File file) {
public static
//#if MC>=11400
//$$ CompletableFuture<?>
//#else
ListenableFuture<?>
//#endif
setServerResourcePack(File file) {
//#if MC>=11300
return getMinecraft().getPackFinder().func_195741_a(file);
//#else
@@ -267,6 +360,35 @@ public class MCVer {
//#endif
}
public static <T> void addCallback(
//#if MC>=11400
//$$ CompletableFuture<T> future,
//#else
ListenableFuture<T> future,
//#endif
Consumer<T> success,
Consumer<Throwable> failure
) {
//#if MC>=11400
//$$ future.thenAccept(success).exceptionally(throwable -> {
//$$ failure.accept(throwable);
//$$ return null;
//$$ });
//#else
Futures.addCallback(future, new FutureCallback<T>() {
@Override
public void onSuccess(T result) {
success.accept(result);
}
@Override
public void onFailure(Throwable throwable) {
failure.accept(throwable);
}
});
//#endif
}
public static void BufferBuilder_setTranslation(double x, double y, double z) {
//#if MC>=10800
Tessellator.getInstance().getBuffer().setTranslation(x, y, z);
@@ -386,12 +508,23 @@ public class MCVer {
return ((MinecraftAccessor) getMinecraft()).getTimer().renderPartialTicks;
}
public static void addButton(GuiScreen screen, GuiButton button) {
GuiScreenAccessor acc = (GuiScreenAccessor) screen;
acc.getButtons().add(button);
//#if MC>=11300
acc.getChildren().add(button);
//#endif
}
//#if MC>=11300
public static void processKeyBinds() {
((MinecraftMethodAccessor) getMinecraft()).replayModProcessKeyBinds();
}
public interface MinecraftMethodAccessor {
void replayModProcessKeyBinds();
//#if MC>=11400
//$$ void replayModExecuteTaskQueue();
//#endif
}
//#endif
@@ -419,6 +552,17 @@ public class MCVer {
return MathHelper.sin(val);
}
//#if MC>=10904
// TODO: this can be inlined once https://github.com/SpongePowered/Mixin/issues/305 is fixed
public static Vec3d getPosition(Particle particle, float partialTicks) {
ParticleAccessor acc = (ParticleAccessor) particle;
double x = acc.getPrevPosX() + (acc.getPosX() - acc.getPrevPosX()) * partialTicks;
double y = acc.getPrevPosY() + (acc.getPosY() - acc.getPrevPosY()) * partialTicks;
double z = acc.getPrevPosZ() + (acc.getPosZ() - acc.getPrevPosZ()) * partialTicks;
return new Vec3d(x, y, z);
}
//#endif
public static void openFile(File file) {
//#if MC>=11300
Util.getOSType().openFile(file);
@@ -535,7 +679,11 @@ public class MCVer {
public static final int KEY_Z = GLFW.GLFW_KEY_Z;
public static boolean isKeyDown(int keyCode) {
//#if MC>=11400
//$$ return InputUtil.isKeyPressed(getMinecraft().window.getHandle(), keyCode);
//#else
return InputMappings.isKeyDown(keyCode);
//#endif
}
}
//#endif