From 868d873fe8de3e715fa139a1d4dcf0050a6d9a85 Mon Sep 17 00:00:00 2001 From: johni0702 Date: Sun, 8 Nov 2015 17:56:48 +0100 Subject: [PATCH] Add player overview extra --- .../com/replaymod/extras/ReplayModExtras.java | 2 + .../extras/playeroverview/PlayerOverview.java | 101 ++++++++++++ .../playeroverview/PlayerOverviewGui.java | 153 ++++++++++++++++++ .../playeroverview/PlayerRenderHook.java | 20 +++ .../gui/container/GuiVerticalList.java | 37 +++++ .../gui/element/AbstractGuiCheckbox.java | 2 +- .../replaymod/registry/KeybindRegistry.java | 2 - 7 files changed, 314 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/replaymod/extras/playeroverview/PlayerOverview.java create mode 100644 src/main/java/com/replaymod/extras/playeroverview/PlayerOverviewGui.java create mode 100644 src/main/java/com/replaymod/extras/playeroverview/PlayerRenderHook.java create mode 100644 src/main/java/de/johni0702/minecraft/gui/container/GuiVerticalList.java diff --git a/src/main/java/com/replaymod/extras/ReplayModExtras.java b/src/main/java/com/replaymod/extras/ReplayModExtras.java index c7249485..5a12402f 100644 --- a/src/main/java/com/replaymod/extras/ReplayModExtras.java +++ b/src/main/java/com/replaymod/extras/ReplayModExtras.java @@ -1,6 +1,7 @@ package com.replaymod.extras; import com.replaymod.core.ReplayMod; +import com.replaymod.extras.playeroverview.PlayerOverview; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; @@ -20,6 +21,7 @@ public class ReplayModExtras { private static ReplayMod core; private static final List> builtin = Arrays.asList( + PlayerOverview.class, FullBrightness.class, HotkeyButtons.class ); diff --git a/src/main/java/com/replaymod/extras/playeroverview/PlayerOverview.java b/src/main/java/com/replaymod/extras/playeroverview/PlayerOverview.java new file mode 100644 index 00000000..fd1f1507 --- /dev/null +++ b/src/main/java/com/replaymod/extras/playeroverview/PlayerOverview.java @@ -0,0 +1,101 @@ +package com.replaymod.extras.playeroverview; + +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import com.replaymod.core.ReplayMod; +import com.replaymod.extras.Extra; +import com.replaymod.replay.ReplayModReplay; +import com.replaymod.replay.camera.CameraEntity; +import com.replaymod.replay.events.ReplayCloseEvent; +import com.replaymod.replay.events.ReplayOpenEvent; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.entity.RenderPlayer; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.lwjgl.input.Keyboard; + +import java.io.IOException; +import java.util.*; + +public class PlayerOverview implements Extra { + @Mod.Instance(ReplayModReplay.MOD_ID) + private static ReplayModReplay module; + + private final Set hiddenPlayers = new HashSet<>(); + private boolean savingEnabled; + + @Override + public void register(final ReplayMod mod) throws Exception { + mod.getKeyBindingRegistry().registerKeyBinding("replaymod.input.playeroverview", Keyboard.KEY_B, new Runnable() { + @Override + public void run() { + if (module.getReplayHandler() != null) { + @SuppressWarnings("unchecked") + List players = mod.getMinecraft().theWorld.getPlayers(EntityPlayer.class, new Predicate() { + @Override + public boolean apply(Object input) { + return !(input instanceof CameraEntity); // Exclude the camera entity + } + }); + new PlayerOverviewGui(PlayerOverview.this, players).display(); + } + } + }); + + FMLCommonHandler.instance().bus().register(this); + + RenderManager renderManager = mod.getMinecraft().getRenderManager(); + @SuppressWarnings("unchecked") + Map skinMap = renderManager.skinMap; + skinMap.put("default", new PlayerRenderHook(this, renderManager, false)); + skinMap.put("slim", new PlayerRenderHook(this, renderManager, true)); + } + + public boolean isHidden(UUID uuid) { + return hiddenPlayers.contains(uuid); + } + + public void setHidden(UUID uuid, boolean hidden) { + if (hidden) { + hiddenPlayers.add(uuid); + } else { + hiddenPlayers.remove(uuid); + } + } + + @SubscribeEvent + public void onReplayOpen(ReplayOpenEvent.Pre event) throws IOException { + Optional> savedData = event.getReplayHandler().getReplayFile().getInvisiblePlayers(); + if (savedData.isPresent()) { + hiddenPlayers.addAll(savedData.get()); + savingEnabled = true; + } else { + savingEnabled = false; + } + } + + @SubscribeEvent + public void onReplayClose(ReplayCloseEvent.Pre event) throws IOException { + hiddenPlayers.clear(); + } + + public boolean isSavingEnabled() { + return savingEnabled; + } + + public void setSavingEnabled(boolean savingEnabled) { + this.savingEnabled = savingEnabled; + } + + public void saveHiddenPlayers() { + if (savingEnabled) { + try { + module.getReplayHandler().getReplayFile().writeInvisiblePlayers(hiddenPlayers); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} diff --git a/src/main/java/com/replaymod/extras/playeroverview/PlayerOverviewGui.java b/src/main/java/com/replaymod/extras/playeroverview/PlayerOverviewGui.java new file mode 100644 index 00000000..6aef31ca --- /dev/null +++ b/src/main/java/com/replaymod/extras/playeroverview/PlayerOverviewGui.java @@ -0,0 +1,153 @@ +package com.replaymod.extras.playeroverview; + +import com.replaymod.replay.ReplayModReplay; +import de.johni0702.minecraft.gui.GuiRenderer; +import de.johni0702.minecraft.gui.RenderInfo; +import de.johni0702.minecraft.gui.container.*; +import de.johni0702.minecraft.gui.element.GuiCheckbox; +import de.johni0702.minecraft.gui.element.GuiImage; +import de.johni0702.minecraft.gui.element.GuiLabel; +import de.johni0702.minecraft.gui.element.IGuiCheckbox; +import de.johni0702.minecraft.gui.function.Closeable; +import de.johni0702.minecraft.gui.layout.CustomLayout; +import de.johni0702.minecraft.gui.layout.HorizontalLayout; +import de.johni0702.minecraft.gui.utils.Colors; +import eu.crushedpixel.replaymod.utils.SkinProvider; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EnumPlayerModelParts; +import net.minecraft.potion.Potion; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.util.Dimension; +import org.lwjgl.util.ReadableDimension; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class PlayerOverviewGui extends GuiScreen implements Closeable { + protected static final int ENTRY_WIDTH = 200; + + public final GuiPanel contentPanel = new GuiPanel(this).setBackgroundColor(Colors.DARK_TRANSPARENT); + public final GuiLabel spectateLabel = new GuiLabel(contentPanel) + .setI18nText("replaymod.gui.playeroverview.spectate"); + public final GuiLabel visibleLabel = new GuiLabel(contentPanel) + .setI18nText("replaymod.gui.playeroverview.visible"); + public final GuiVerticalList playersScrollable = new GuiVerticalList(contentPanel) + .setDrawSlider(true).setDrawShadow(true); + public final GuiCheckbox saveCheckbox = new GuiCheckbox(contentPanel) + .setI18nLabel("replaymod.gui.playeroverview.remembersettings"); + public final GuiCheckbox checkAll = new GuiCheckbox(contentPanel){ + @Override + public void onClick() { + getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(BUTTON_SOUND, 1.0F)); + playersScrollable.forEach(IGuiCheckbox.class).setChecked(true); + } + }.setLabel("").setChecked(true); + public final GuiCheckbox uncheckAll = new GuiCheckbox(contentPanel){ + @Override + public void onClick() { + getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(BUTTON_SOUND, 1.0F)); + playersScrollable.forEach(IGuiCheckbox.class).setChecked(false); + } + }.setLabel("").setChecked(false); + + { + setDrawBackground(false); + setTitle(new GuiLabel().setI18nText("replaymod.input.playeroverview")); + setLayout(new CustomLayout() { + @Override + protected void layout(GuiScreen container, int width, int height) { + size(contentPanel, ENTRY_WIDTH + 30, height - 40); + pos(contentPanel, width / 2 - width(contentPanel) / 2, 20); + } + }); + contentPanel.setLayout(new CustomLayout() { + @Override + protected void layout(GuiPanel container, int width, int height) { + pos(spectateLabel, 10, 10); + pos(visibleLabel, width - 10 - width(visibleLabel), 10); + pos(playersScrollable, 10, y(spectateLabel) + height(spectateLabel) + 5); + size(playersScrollable, width - 10 - 5, height - 15 - height(saveCheckbox) - y(playersScrollable)); + pos(saveCheckbox, 10, height - 10 - height(saveCheckbox)); + pos(uncheckAll, width - width(uncheckAll) - 8, height - height(uncheckAll) - 10); + pos(checkAll, x(uncheckAll) - 3 - width(checkAll), y(uncheckAll)); + } + }); + } + + private final PlayerOverview extra; + + public PlayerOverviewGui(final PlayerOverview extra, List players) { + this.extra = extra; + + Collections.sort(players, new PlayerComparator()); // Sort by name, spectators last + for (final EntityPlayer p : players) { + final ResourceLocation texture = SkinProvider.getResourceLocationForPlayerUUID(p.getUniqueID()); + final GuiClickable panel = new GuiClickable().setLayout(new HorizontalLayout().setSpacing(2)).addElements( + new HorizontalLayout.Data(0.5), new GuiImage() { + @Override + public void draw(GuiRenderer renderer, ReadableDimension size, RenderInfo renderInfo) { + renderer.bindTexture(texture); + renderer.drawTexturedRect(0, 0, 8, 8, 16, 16, 8, 8, 64, 64); + if (p.func_175148_a(EnumPlayerModelParts.HAT)) { + renderer.drawTexturedRect(0, 0, 40, 8, size.getWidth(), size.getHeight(), 8, 8, 64, 64); + } + } + }.setSize(16, 16), + new GuiLabel().setText(p.getName()).setColor(isSpectator(p) ? Colors.DKGREY : Colors.WHITE) + ).onClick(new Runnable() { + @Override + public void run() { + ReplayModReplay.instance.getReplayHandler().spectateEntity(p); + } + }); + final GuiCheckbox checkbox = new GuiCheckbox() { + @Override + public GuiCheckbox setChecked(boolean checked) { + extra.setHidden(p.getUniqueID(), !checked); + return super.setChecked(checked); + } + }.setChecked(!extra.isHidden(p.getUniqueID())); + new GuiPanel(playersScrollable.getListPanel()).setLayout(new CustomLayout() { + @Override + protected void layout(GuiPanel container, int width, int height) { + pos(panel, 5, 0); + pos(checkbox, width - width(checkbox) - 5, height / 2 - height(checkbox) / 2); + } + + @Override + public ReadableDimension calcMinSize(GuiContainer container) { + return new Dimension(ENTRY_WIDTH, panel.getMinSize().getHeight()); + } + }).addElements(null, panel, checkbox); + } + saveCheckbox.setChecked(extra.isSavingEnabled()).onClick(new Runnable() { + @Override + public void run() { + extra.setSavingEnabled(saveCheckbox.isChecked()); + } + }); + + ReplayModReplay.instance.getReplayHandler().getOverlay().setVisible(false); + } + + @Override + public void close() { + ReplayModReplay.instance.getReplayHandler().getOverlay().setVisible(false); + extra.saveHiddenPlayers(); + } + + private static boolean isSpectator(EntityPlayer e) { + return e.isInvisible() && e.getActivePotionEffect(Potion.invisibility) == null; + } + + private static final class PlayerComparator implements Comparator { + @Override + public int compare(EntityPlayer o1, EntityPlayer o2) { + if (isSpectator(o1) && !isSpectator(o2)) return 1; + if (isSpectator(o2) && !isSpectator(o1)) return -1; + return o1.getName().compareToIgnoreCase(o2.getName()); + } + } +} diff --git a/src/main/java/com/replaymod/extras/playeroverview/PlayerRenderHook.java b/src/main/java/com/replaymod/extras/playeroverview/PlayerRenderHook.java new file mode 100644 index 00000000..66c7eb42 --- /dev/null +++ b/src/main/java/com/replaymod/extras/playeroverview/PlayerRenderHook.java @@ -0,0 +1,20 @@ +package com.replaymod.extras.playeroverview; + +import net.minecraft.client.renderer.culling.ICamera; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.entity.RenderPlayer; +import net.minecraft.entity.Entity; + +public class PlayerRenderHook extends RenderPlayer { + private final PlayerOverview extra; + + public PlayerRenderHook(PlayerOverview extra, RenderManager renderManager, boolean useSmallArms) { + super(renderManager, useSmallArms); + this.extra = extra; + } + + @Override + public boolean shouldRender(Entity entity, ICamera camera, double camX, double camY, double camZ) { + return !extra.isHidden(entity.getUniqueID()) && super.shouldRender(entity, camera, camX, camY, camZ); + } +} diff --git a/src/main/java/de/johni0702/minecraft/gui/container/GuiVerticalList.java b/src/main/java/de/johni0702/minecraft/gui/container/GuiVerticalList.java new file mode 100644 index 00000000..78d113da --- /dev/null +++ b/src/main/java/de/johni0702/minecraft/gui/container/GuiVerticalList.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015 johni0702 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package de.johni0702.minecraft.gui.container; + +public class GuiVerticalList extends AbstractGuiVerticalList { + public GuiVerticalList() { + } + + public GuiVerticalList(GuiContainer container) { + super(container); + } + + @Override + protected GuiVerticalList getThis() { + return this; + } +} diff --git a/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiCheckbox.java b/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiCheckbox.java index cdd652c8..f9632b02 100644 --- a/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiCheckbox.java +++ b/src/main/java/de/johni0702/minecraft/gui/element/AbstractGuiCheckbox.java @@ -89,7 +89,7 @@ public abstract class AbstractGuiCheckbox> @Override public void onClick() { getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(BUTTON_SOUND, 1.0F)); - checked = !checked; + setChecked(!isChecked()); super.onClick(); } diff --git a/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java b/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java index 1224afc4..f06a7766 100755 --- a/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java +++ b/src/main/java/eu/crushedpixel/replaymod/registry/KeybindRegistry.java @@ -45,8 +45,6 @@ public class KeybindRegistry { replayModKeyBindings.add(new KeyBinding(KEY_SYNC_TIMELINE, Keyboard.KEY_V, "replaymod.title")); - replayModKeyBindings.add(new KeyBinding(KEY_PLAYER_OVERVIEW, Keyboard.KEY_B, "replaymod.title")); - replayModKeyBindings.add(new KeyBinding(KEY_ASSET_MANAGER, Keyboard.KEY_G, "replaymod.title")); replayModKeyBindings.add(new KeyBinding(KEY_OBJECT_MANAGER, Keyboard.KEY_F, "replaymod.title"));