diff --git a/src/main/java/com/zivilon/cinder_loe/CinderEventHandler.java b/src/main/java/com/zivilon/cinder_loe/CinderEventHandler.java index 56e75ee..86b9fdc 100644 --- a/src/main/java/com/zivilon/cinder_loe/CinderEventHandler.java +++ b/src/main/java/com/zivilon/cinder_loe/CinderEventHandler.java @@ -2,12 +2,15 @@ package com.zivilon.cinder_loe; import com.zivilon.cinder_loe.entity.corrupt.CorruptMan; import com.zivilon.cinder_loe.items.BrokenHalo; +import com.zivilon.cinder_loe.network.PacketWarbandLocations; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.IFuelHandler; import cpw.mods.fml.common.eventhandler.EventPriority; import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.common.registry.GameRegistry; import lotr.common.LOTRMod; +import lotr.common.LOTRDimension; import lotr.common.enchant.LOTREnchantment; import lotr.common.enchant.LOTREnchantmentHelper; import lotr.common.item.*; @@ -32,6 +35,7 @@ import net.minecraft.util.DamageSource; import net.minecraft.util.EnumChatFormatting; import net.minecraft.world.World; import net.minecraft.world.WorldServer; +import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingHurtEvent; @@ -47,6 +51,23 @@ public class CinderEventHandler implements IFuelHandler { MinecraftForge.TERRAIN_GEN_BUS.register(this); GameRegistry.registerFuelHandler(this); } + + @SubscribeEvent + public void onWorldTick(TickEvent.WorldTickEvent event) { + World world = event.world; + if (world.isRemote) + return; + if (event.phase == TickEvent.Phase.END) { + if (world == DimensionManager.getWorld(LOTRDimension.MIDDLE_EARTH.dimensionID)) { + if (!world.playerEntities.isEmpty()) { + if (world.getTotalWorldTime() % 20L == 0L) { + PacketWarbandLocations.send_warband_locations(world); + } + } + } + } + } + @SubscribeEvent public void onArrowLoose(ArrowLooseEvent event) { Entity attacker = event.entityLiving; diff --git a/src/main/java/com/zivilon/cinder_loe/CinderLoE.java b/src/main/java/com/zivilon/cinder_loe/CinderLoE.java index e1a2279..4079fa5 100644 --- a/src/main/java/com/zivilon/cinder_loe/CinderLoE.java +++ b/src/main/java/com/zivilon/cinder_loe/CinderLoE.java @@ -7,6 +7,7 @@ import com.zivilon.cinder_loe.client.render.*; import com.zivilon.cinder_loe.client.render.corrupt.*; import com.zivilon.cinder_loe.client.render.projectile.*; import com.zivilon.cinder_loe.command.CommandCinderCharacter; +import com.zivilon.cinder_loe.command.CommandWarband; import com.zivilon.cinder_loe.entity.*; import com.zivilon.cinder_loe.entity.corrupt.*; import com.zivilon.cinder_loe.entity.npc.*; @@ -23,6 +24,7 @@ import com.zivilon.cinder_loe.entity.npc.radagast.*; import com.zivilon.cinder_loe.entity.projectile.*; import com.zivilon.cinder_loe.entity.trader.*; import com.zivilon.cinder_loe.items.*; +import com.zivilon.cinder_loe.network.*; import com.zivilon.cinder_loe.potion.LoEPotions; import com.zivilon.cinder_loe.tileentity.*; import com.zivilon.cinder_loe.util.Utilities; @@ -321,6 +323,7 @@ public class CinderLoE { registerBlocks(); registerItems(); ItemRegistration.registerItems(); + PacketRegistration.register(); registerEntities(); modEventHandler = new CinderEventHandler(); LoEPotions.registerPotions(); @@ -359,6 +362,7 @@ public class CinderLoE { public void serverStarting(FMLServerStartingEvent event) { CharacterRoleAPI.loadRolesFromFile(); event.registerServerCommand(new CommandCinderCharacter()); + event.registerServerCommand(new CommandWarband()); } public void registerEntities() { // Last ID added: 60 diff --git a/src/main/java/com/zivilon/cinder_loe/command/CommandWarband.java b/src/main/java/com/zivilon/cinder_loe/command/CommandWarband.java new file mode 100644 index 0000000..2b4dc85 --- /dev/null +++ b/src/main/java/com/zivilon/cinder_loe/command/CommandWarband.java @@ -0,0 +1,151 @@ +package com.zivilon.cinder_loe.command; + +import com.zivilon.cinder_loe.world.event.Warband; +import com.zivilon.cinder_loe.world.event.WarbandFaction; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.ChatComponentText; + +import lotr.common.world.map.LOTRWaypoint; + +import com.zivilon.cinder_loe.character.CharacterRoleAPI; +import com.zivilon.cinder_loe.util.Utilities; + +import java.util.UUID; + +public class CommandWarband extends CommandBase { + @Override + public String getCommandName() { + return "warband"; + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return "/warband [faction_name] [waypoint] [x] [z]"; + } + + @Override + public int getRequiredPermissionLevel() { + return 4; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + if(!validate_args(args)) { + sender.addChatMessage(new ChatComponentText("Incorrect arguments. Usage: " + getCommandUsage(sender))); + return; + } + + String action = args[0]; + System.out.println("Checking arg " + action); + switch (action) { + case "reset": + reset_warband(); + sender.addChatMessage(new ChatComponentText("Warband timer has been reset. A new warband may now spawn.")); + return; + case "list": + list_warbands(sender); + return; + case "summon": + summon_warband(sender, args); + return; + } + } + + public void summon_warband(ICommandSender sender, String[] args) { + WarbandFaction faction = WarbandFaction.get_warband_by_name(args[1]); + LOTRWaypoint waypoint = null; + String waypoint_name = null; + int x = 0; + int z = 0; + + if (args.length == 2) { + if (!(sender instanceof EntityPlayer)) { + System.out.println("Console must specify location to summon warband. Options:"); + System.out.println("/warband "); + System.out.println("/warband "); + return; + } + EntityPlayer player = (EntityPlayer)sender; + x = (int)player.posX; + z = (int)player.posZ; + Warband.initialize_warband(faction, x, z); + } + + if (args.length == 3) { + waypoint_name = args[2]; + waypoint = LOTRWaypoint.waypointForName(waypoint_name); + if (waypoint == null) { + sender.addChatMessage(new ChatComponentText("Invalid waypoint \"" + waypoint_name + "\"")); + } + Warband.initialize_warband(faction, waypoint); + return; + } + + if (args.length == 4) { + try { + x = Integer.parseInt(args[2]); + z = Integer.parseInt(args[3]); + } catch (Exception e) { + sender.addChatMessage(new ChatComponentText("Invalid coordinates provided")); + return; + } + Warband.initialize_warband(faction, x, z); + return; + } + + if (args.length > 4) { + try { + x = Integer.parseInt(args[3]); + z = Integer.parseInt(args[4]); + } catch (Exception e) { + sender.addChatMessage(new ChatComponentText("Invalid coordinates provided")); + return; + } + waypoint_name = args[2]; + waypoint = LOTRWaypoint.waypointForName(waypoint_name); + if (waypoint == null) { + sender.addChatMessage(new ChatComponentText("Invalid waypoint \"" + waypoint_name + "\"")); + return; + } + Warband.initialize_warband(faction, waypoint, x, z); + return; + } + } + + public static boolean validate_args(String[] args) { + System.out.println("Validating..."); + if (args.length < 1) return false; + String action = ""; + System.out.println("Checking arg \"" + args[0] + "\""); + if (args[0].equals("summon") || args[0].equals("reset") || args[0].equals("list")) { + action = args[0]; + } else { + System.out.println("Failed test 1"); + return false; + } + if (action.equals("summon")) { + if (args.length < 2) { + System.out.println("Failed test 2"); + return false; + } + WarbandFaction faction = WarbandFaction.get_warband_by_name(args[1]); + if (faction == null) return false; + } + return true; + } + + public static void reset_warband() { + // Set last warband to have happened 10 hours ago, thus allowing new warband + Warband.last_warband_timestamp = System.currentTimeMillis() / 1000L - (60*60*10); + } + public static void list_warbands(ICommandSender sender) { + sender.addChatMessage(new ChatComponentText("List of valid warbands:")); + for (WarbandFaction faction : WarbandFaction.values()) { + sender.addChatMessage(new ChatComponentText("- " + faction.name())); + } + } +} diff --git a/src/main/java/com/zivilon/cinder_loe/droptables/DropTable.java b/src/main/java/com/zivilon/cinder_loe/droptables/DropTable.java index b472e03..c980bc3 100644 --- a/src/main/java/com/zivilon/cinder_loe/droptables/DropTable.java +++ b/src/main/java/com/zivilon/cinder_loe/droptables/DropTable.java @@ -27,7 +27,7 @@ public class DropTable { public static void drop_items(LOTREntityNPC entity, DropContext[] context_flags, int looting_level) { List drops = generate_drops(entity, context_flags, looting_level); - if (drops == null) return; + if (drops == null || drops.size() < 1) return; for (ItemStack drop : drops) { entity.npcDropItem(drop, 0.0F, false, false); } @@ -35,9 +35,12 @@ public class DropTable { public static List generate_drops(LOTREntityNPC entity, DropContext[] context_flags, int looting_level) { DropTable table = ((ILootableEntity)entity).get_drop_table(); - if (table == null) return null; - if (context_flags == null) context_flags = new DropContext[0]; - + if (table == null) { + return null; + } + if (context_flags == null) { + context_flags = new DropContext[0]; + } List results = new ArrayList<>(); for (DropInstance drop : table.drop_list) { ItemStack stack = get_drop(drop, looting_level, context_flags); @@ -49,8 +52,7 @@ public class DropTable { } public static ItemStack get_drop(DropInstance drop, int looting_level, DropContext[] context) { - if (!(Utilities.array_contains_array(drop.conditions, context))) return null; - + if (!(Utilities.array_contains_array(context, drop.conditions))) return null; if (drop instanceof SingleItemDrop) { return get_single_drop((SingleItemDrop)drop, looting_level); } diff --git a/src/main/java/com/zivilon/cinder_loe/mixins/MixinEntityLivingBase.java b/src/main/java/com/zivilon/cinder_loe/mixins/MixinEntityLivingBase.java index 7f10045..ade4623 100644 --- a/src/main/java/com/zivilon/cinder_loe/mixins/MixinEntityLivingBase.java +++ b/src/main/java/com/zivilon/cinder_loe/mixins/MixinEntityLivingBase.java @@ -1,6 +1,9 @@ package com.zivilon.cinder_loe.mixins; import com.zivilon.cinder_loe.util.*; +import com.zivilon.cinder_loe.world.event.Warband; +import com.zivilon.cinder_loe.world.event.WarbandLocationInfo; +import com.zivilon.cinder_loe.world.event.WarbandTracker; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.*; @@ -15,7 +18,10 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.Potion; import net.minecraft.server.MinecraftServer; +import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.ChatComponentText; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.ChatStyle; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumChatFormatting; import net.minecraft.world.World; @@ -257,14 +263,36 @@ public abstract class MixinEntityLivingBase extends Entity implements IEntityLiv } } + public void setDead() { + super.setDead(); + if (this.warband_uuid != null && this.warband_uuid.equals(this.getUniqueID())) { + WarbandLocationInfo info = WarbandTracker.locations.get(this.warband_uuid); + String faction_name = ""; + if (info != null && info.warband != null && info.warband.faction != null) { + faction_name = info.warband.faction.faction.untranslatedFactionName(); + } + ChatComponentTranslation message; + if (!faction_name.equals("")) { + message = new ChatComponentTranslation( + "warband.defeated.faction", + new ChatComponentTranslation(faction_name) + ); + } else { + message = new ChatComponentTranslation( + "warband.defeated.no_faction" + ); + } + message.setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GRAY)); + MinecraftServer.getServer().getConfigurationManager().sendChatMsg(message); + WarbandTracker.remove(this.warband_uuid); + } + } + @Inject(method = "onUpdate", at = @At("TAIL")) private void onUpdate(CallbackInfo ci) { if (despawn_timer > -1) { despawn_timer--; if (despawn_timer == 0) { - if (warband_uuid == ((EntityLivingBase)(Object)this).getUniqueID()) { - MinecraftServer.getServer().getConfigurationManager().sendChatMsg(new ChatComponentText(EnumChatFormatting.GRAY + "Warband has disbanded")); - } ((EntityLivingBase)(Object)this).setDead(); } } diff --git a/src/main/java/com/zivilon/cinder_loe/mixins/MixinLOTREntityAIOrcSkirmish.java b/src/main/java/com/zivilon/cinder_loe/mixins/MixinLOTREntityAIOrcSkirmish.java new file mode 100644 index 0000000..3d56d18 --- /dev/null +++ b/src/main/java/com/zivilon/cinder_loe/mixins/MixinLOTREntityAIOrcSkirmish.java @@ -0,0 +1,26 @@ +package com.zivilon.cinder_loe.mixins; + +import com.zivilon.cinder_loe.util.IEntityLivingBase; + +import lotr.common.entity.npc.LOTREntityOrc; +import lotr.common.entity.ai.LOTREntityAIOrcSkirmish; + +import net.minecraft.entity.EntityLivingBase; + +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.*; +import org.spongepowered.asm.mixin.injection.callback.*; + +@Mixin(LOTREntityAIOrcSkirmish.class) +public class MixinLOTREntityAIOrcSkirmish { + + @Overwrite(remap = false) + private boolean canOrcSkirmish(EntityLivingBase entity) { + if (entity instanceof LOTREntityOrc) { + LOTREntityOrc orc = (LOTREntityOrc)entity; + if (((IEntityLivingBase)orc).get_warband_uuid() != null) return false; + return (!orc.isTrader() && !orc.hiredNPCInfo.isActive && orc.ridingEntity == null && orc.canOrcSkirmish()); + } + return false; + } +} diff --git a/src/main/java/com/zivilon/cinder_loe/mixins/MixinLOTRGuiMap.java b/src/main/java/com/zivilon/cinder_loe/mixins/MixinLOTRGuiMap.java new file mode 100644 index 0000000..3a89dea --- /dev/null +++ b/src/main/java/com/zivilon/cinder_loe/mixins/MixinLOTRGuiMap.java @@ -0,0 +1,139 @@ +package com.zivilon.cinder_loe.mixins; + +import com.zivilon.cinder_loe.world.event.Warband; +import com.zivilon.cinder_loe.world.event.WarbandTracker; +import com.zivilon.cinder_loe.world.event.WarbandLocationInfo; + +import lotr.client.gui.LOTRGuiMap; +import lotr.client.gui.LOTRGuiMenuBase; +import lotr.client.LOTRClientProxy; +import lotr.common.LOTRLevelData; +import lotr.common.fac.LOTRFaction; + +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.StatCollector; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.lwjgl.opengl.GL11; + +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.*; +import org.spongepowered.asm.mixin.injection.callback.*; + + +@Mixin(LOTRGuiMap.class) +public abstract class MixinLOTRGuiMap extends LOTRGuiMenuBase { + private static Map warband_locations = WarbandTracker.locations; + private static ResourceLocation WARBAND_ICON = new ResourceLocation("cinderloe", "textures/gui/alignment.png"); + + @Shadow(remap = false) + private boolean loadingConquestGrid; + @Shadow(remap = false) + private boolean hasOverlay; + @Shadow(remap = false) + private static int mapXMin; + @Shadow(remap = false) + private static int mapXMax; + @Shadow(remap = false) + private static int mapYMin; + @Shadow(remap = false) + private static int mapYMax; + @Shadow(remap = false) + private void drawFancyRect(int x1, int y1, int x2, int y2) {} + @Shadow(remap = false) + public float[] transformCoords(float x, float z) { return null;} + + @Inject(method = "func_73863_a", at = @At("HEAD"), remap = false) + public void inject_head(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) { + System.out.println("[MixinLOTRGuiMap] Inject at HEAD"); + } + @Inject(method = "func_73863_a", at = @At( value = "INVOKE", target = "renderPlayers(II)V", shift = At.Shift.AFTER), remap = false) + public void inject_render_warbands(int mouseX, int mouseY, float partialTicks, CallbackInfo ci) { + System.out.println("[MixinLOTRGuiMap] Running wrapper"); + render_warbands(mouseX, mouseY); + } + + @Dynamic + private void render_warbands(int cursor_x, int cursor_y) { + System.out.println("[MixinLOTRGuiMap] Rendering warband icon"); + String mouse_over_warband_name = null; + double mouse_over_warband_x = 0.0D; + double mouse_over_warband_y = 0.0D; + double shortest_distance_to_cursor = Double.MAX_VALUE; + int icon_width_half = 4; + for (Map.Entry entry : warband_locations.entrySet()) { + System.out.println("[MixinLOTRGuiMap] Iterated"); + WarbandLocationInfo info = entry.getValue(); + Warband warband = info.warband; + String warband_name = warband.faction.warband_name; + float[] pos = transformCoords((float)info.x, (float)info.z); + int map_x = Math.round(pos[0]); + int map_y = Math.round(pos[1]); + + double distance_to_icon = render_warband_icon(warband, map_x, map_y, cursor_x, cursor_y); + if (distance_to_icon <= (icon_width_half + 3)) { + if (distance_to_icon <= shortest_distance_to_cursor) { + mouse_over_warband_name = StatCollector.translateToLocal(warband_name); + mouse_over_warband_x = map_x; + mouse_over_warband_y = map_y; + shortest_distance_to_cursor = distance_to_icon; + } + } + } + if (mouse_over_warband_name != null && !this.hasOverlay && !this.loadingConquestGrid) { + int name_width = this.mc.fontRenderer.getStringWidth(mouse_over_warband_name); + int name_height = this.mc.fontRenderer.FONT_HEIGHT; + int namebox_x = (int)Math.round(mouse_over_warband_x); + int namebox_y = (int)Math.round(mouse_over_warband_y); + namebox_y += icon_width_half + 3; + int border = 3; + int namebox_width = name_width + border * 2; + namebox_x -= namebox_width / 2; + int namebox_height = name_height + border * 2; + int map_border = 2; + namebox_x = Math.max(namebox_x, mapXMin + map_border); + namebox_x = Math.min(namebox_x, mapXMax - map_border - namebox_width); + namebox_y = Math.max(namebox_y, mapYMin + map_border); + namebox_y = Math.min(namebox_y, mapYMax - map_border - namebox_height); + GL11.glTranslatef(0.0F, 0.0F, 300.0F); + drawFancyRect(namebox_x, namebox_y, namebox_x + namebox_width, namebox_y + namebox_height); + this.mc.fontRenderer.drawString(mouse_over_warband_name, namebox_x + border, namebox_y + border, 16777215); + GL11.glTranslatef(0.0F, 0.0F, -300.0F); + } + } + + @Dynamic + private double render_warband_icon(Warband warband, double map_x, double map_y, int mouse_x, int mouse_y) { + int icon_half = 4; + int icon_border = icon_half + 1; + + map_x = Math.max(mapXMin + icon_border, Math.min(mapXMax - icon_border - 1, map_x)); + map_y = Math.max(mapYMin + icon_border, Math.min(mapYMax - icon_border - 1, map_y)); + + // Determine ally/enemy icon + LOTRFaction faction = warband.faction.faction; + float alignment = LOTRLevelData.getData(mc.thePlayer).getAlignment(faction); + boolean is_ally = alignment > 0.0F; + + load_warband_icon(is_ally, (int) map_x, (int) map_y); + + // Return mouse distance to icon + double dx = map_x - mouse_x; + double dy = map_y - mouse_y; + return Math.hypot(dx, dy); + } + + + @Dynamic + private void load_warband_icon(boolean ally, int x, int y) { + System.out.println("[MixinLOTRGuiMap] Loading warband icon: " + (ally ? "ally" : "enemy")); + mc.getTextureManager().bindTexture(LOTRClientProxy.alignmentTexture); + GL11.glColor4f(1F, 1F, 1F, 1F); + int variant = ally ? 16 : 0; + drawTexturedModalRect(x - 8, y - 8, variant, 228, 16, 16); + } + +} diff --git a/src/main/java/com/zivilon/cinder_loe/network/PacketRegistration.java b/src/main/java/com/zivilon/cinder_loe/network/PacketRegistration.java new file mode 100644 index 0000000..e2a9114 --- /dev/null +++ b/src/main/java/com/zivilon/cinder_loe/network/PacketRegistration.java @@ -0,0 +1,12 @@ +package com.zivilon.cinder_loe.network; + +import com.zivilon.cinder_loe.network.PacketWarbandLocations.Handler; +import lotr.common.network.LOTRPacketHandler; +import cpw.mods.fml.relauncher.Side; + +public class PacketRegistration { + public static void register() { + int id = 200; + LOTRPacketHandler.networkWrapper.registerMessage(PacketWarbandLocations.Handler.class, PacketWarbandLocations.class, id++, Side.CLIENT); + } +} diff --git a/src/main/java/com/zivilon/cinder_loe/network/PacketWarbandLocations.java b/src/main/java/com/zivilon/cinder_loe/network/PacketWarbandLocations.java new file mode 100644 index 0000000..d1e08e5 --- /dev/null +++ b/src/main/java/com/zivilon/cinder_loe/network/PacketWarbandLocations.java @@ -0,0 +1,115 @@ +package com.zivilon.cinder_loe.network; + +import com.zivilon.cinder_loe.world.event.Warband; +import com.zivilon.cinder_loe.world.event.WarbandFaction; +import com.zivilon.cinder_loe.world.event.WarbandLocationInfo; +import com.zivilon.cinder_loe.world.event.WarbandTracker; + +import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import lotr.common.LOTRMod; +import lotr.common.network.LOTRPacketHandler; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.network.PacketBuffer; +import net.minecraft.world.World; + +public class PacketWarbandLocations implements IMessage { + public List locations = WarbandTracker.get_all(); + + @Override + public void toBytes(ByteBuf buf) { + buf.writeShort(locations.size()); + for (WarbandLocationInfo loc : locations) { + buf.writeLong(loc.warband.warband_uuid.getMostSignificantBits()); + buf.writeLong(loc.warband.warband_uuid.getLeastSignificantBits()); + buf.writeDouble(loc.x); + buf.writeDouble(loc.z); + PacketBuffer packet = new PacketBuffer(buf); + write_string_to_buffer(packet, loc.warband.faction.name()); + } + } + + @Override + + public void fromBytes(ByteBuf buf) { + locations.clear(); + int count = buf.readShort(); + for (int i = 0; i < count; i++) { + long msb = buf.readLong(); + long lsb = buf.readLong(); + UUID uuid = new UUID(msb, lsb); + double x = buf.readDouble(); + double z = buf.readDouble(); + + PacketBuffer packet = new PacketBuffer(buf); + String faction_name = read_string_from_buffer(packet, Short.MAX_VALUE); + + WarbandFaction faction = WarbandFaction.get_warband_by_name(faction_name); + + Warband dummy = new Warband(); + dummy.warband_uuid = uuid; + dummy.faction = faction; + dummy.x = (int) x; + dummy.z = (int) z; + locations.add(new WarbandLocationInfo(dummy, x, z)); + } + } + + public static class Handler implements IMessageHandler { + @Override + public IMessage onMessage(PacketWarbandLocations message, MessageContext ctx) { + if (ctx.side.isServer()) { + System.out.println("[PacketWarbandLocations] WARNING: Client tried to update locations on server!"); + return null; + } + + WarbandTracker.clear_locations(); + for (WarbandLocationInfo info : message.locations) { + WarbandTracker.add(info); + } + return null; + } + } + + public static void send_warband_locations(World world) { + for (int i = 0; i < world.playerEntities.size(); i++) { + EntityPlayer entityplayer = (EntityPlayer)world.playerEntities.get(i); + send_location(entityplayer, world); + } + } + + public static void send_location(EntityPlayer player, World world) { + PacketWarbandLocations locations = new PacketWarbandLocations(); + LOTRPacketHandler.networkWrapper.sendTo((IMessage)locations, (EntityPlayerMP)player); + } + public static void write_string_to_buffer(PacketBuffer buffer, String string) { + try { + buffer.writeStringToBuffer(string); + } catch (IOException e) { + throw new RuntimeException("[PacketWarbandLocations] WARNING: Failed to write warband faction", e); + } + } + + public static String read_string_from_buffer(PacketBuffer buffer, int max_length) { + try { + return buffer.readStringFromBuffer(max_length); + } catch (IOException e) { + throw new RuntimeException("[PacketWarbandLocations] WARNING: Failed to read warband faction", e); + } + } + +} diff --git a/src/main/java/com/zivilon/cinder_loe/util/Utilities.java b/src/main/java/com/zivilon/cinder_loe/util/Utilities.java index 5f9c676..8f9f5fe 100644 --- a/src/main/java/com/zivilon/cinder_loe/util/Utilities.java +++ b/src/main/java/com/zivilon/cinder_loe/util/Utilities.java @@ -3,6 +3,7 @@ package com.zivilon.cinder_loe.util; import com.zivilon.cinder_loe.CinderLoE; import com.zivilon.cinder_loe.client.render.item.RenderHelper; import com.zivilon.cinder_loe.mixins.MixinEntity; +import com.zivilon.cinder_loe.droptables.*; import java.io.BufferedWriter; import java.io.FileOutputStream; diff --git a/src/main/java/com/zivilon/cinder_loe/world/event/Warband.java b/src/main/java/com/zivilon/cinder_loe/world/event/Warband.java index 6de85ef..07687a8 100644 --- a/src/main/java/com/zivilon/cinder_loe/world/event/Warband.java +++ b/src/main/java/com/zivilon/cinder_loe/world/event/Warband.java @@ -18,6 +18,8 @@ import net.minecraft.server.MinecraftServer; import net.minecraft.util.*; import net.minecraft.world.World; +import cpw.mods.fml.common.FMLCommonHandler; + import lotr.common.LOTRDimension; import lotr.common.LOTRMod; import lotr.common.entity.npc.LOTRSpeech; @@ -32,13 +34,19 @@ import java.util.UUID; public class Warband { public static Random random = new Random(); - public static World world = MinecraftServer.getServer().worldServerForDimension(LOTRDimension.MIDDLE_EARTH.dimensionID); - public static long last_warband_timestamp = System.currentTimeMillis() / 1000L - (60*60*4); + public static World world;; + public static long last_warband_timestamp = System.currentTimeMillis() / 1000L - (60*60*2); // Initialize at 2 hour cooldown on server startup + + static { + if (FMLCommonHandler.instance().getSide().isServer()) { + world = MinecraftServer.getServer().worldServerForDimension(LOTRDimension.MIDDLE_EARTH.dimensionID); + } + } public int x = 0; public int z = 0; - public String direction = "null"; - public String waypoint_name = "null"; + public String direction = null; + public String waypoint_name = null; public WarbandFaction faction = null; public UUID warband_uuid = null; @@ -52,32 +60,50 @@ public class Warband { } public static void initialize_warband() { + LOTRWaypoint waypoint = get_random_waypoint(); + initialize_warband(null, waypoint, true, null, null); + } + public static void initialize_warband(WarbandFaction faction, LOTRWaypoint waypoint) { + initialize_warband(faction, waypoint, true, null, null); + } + public static void initialize_warband(WarbandFaction faction, Integer x, Integer z) { + initialize_warband(faction, null, false, x, z); + } + public static void initialize_warband(WarbandFaction faction, LOTRWaypoint waypoint, Integer x, Integer z) { + initialize_warband(faction, waypoint, false, x, z); + } + public static void initialize_warband(WarbandFaction faction, LOTRWaypoint waypoint, boolean randomize, Integer x, Integer z) { if (MinecraftServer.getServer().getConfigurationManager().playerEntityList.size() < 1) return; Warband warband = new Warband(); - LOTRWaypoint waypoint = get_random_waypoint(); - warband.waypoint_name = "lotr.waypoint." + waypoint.getCodeName(); - - warband.x = waypoint.getXCoord(); - warband.z = waypoint.getZCoord(); - - switch (random.nextInt(8)) { - case 0: warband.direction = "North"; warband.z += random.nextInt(701) - 1000; break; - case 1: warband.direction = "South"; warband.z += random.nextInt(701) + 300; break; - case 2: warband.direction = "East"; warband.x += random.nextInt(701) + 300; break; - case 3: warband.direction = "West"; warband.x += random.nextInt(701) - 1000; break; - case 4: warband.direction = "North-East"; warband.z += random.nextInt(701) - 1000; warband.x += random.nextInt(701) + 300; break; - case 5: warband.direction = "North-West"; warband.z += random.nextInt(701) - 1000; warband.x += random.nextInt(701) - 1000; break; - case 6: warband.direction = "South-East"; warband.z += random.nextInt(701) + 300; warband.x += random.nextInt(701) + 300; break; - case 7: warband.direction = "South-West"; warband.z += random.nextInt(701) + 300; warband.x += random.nextInt(701) - 1000; break; - default: warband.direction = "none"; break; + if (waypoint != null) warband.waypoint_name = "lotr.waypoint." + waypoint.getCodeName(); + + if ((x == null || z == null) && waypoint == null) waypoint = get_random_waypoint(); + if (x == null) x = waypoint.getXCoord(); + if (z == null) z = waypoint.getZCoord(); + warband.x = x; + warband.z = z; + + if (randomize) { + switch (random.nextInt(8)) { + case 0: warband.direction = "North"; warband.z += random.nextInt(701) - 1000; break; + case 1: warband.direction = "South"; warband.z += random.nextInt(701) + 300; break; + case 2: warband.direction = "East"; warband.x += random.nextInt(701) + 300; break; + case 3: warband.direction = "West"; warband.x += random.nextInt(701) - 1000; break; + case 4: warband.direction = "North-East"; warband.z += random.nextInt(701) - 1000; warband.x += random.nextInt(701) + 300; break; + case 5: warband.direction = "North-West"; warband.z += random.nextInt(701) - 1000; warband.x += random.nextInt(701) - 1000; break; + case 6: warband.direction = "South-East"; warband.z += random.nextInt(701) + 300; warband.x += random.nextInt(701) + 300; break; + case 7: warband.direction = "South-West"; warband.z += random.nextInt(701) + 300; warband.x += random.nextInt(701) - 1000; break; + default: warband.direction = "none"; break; + } } - System.out.println("Loading warband chunks at " + warband.x + "," + warband.z); load_chunks_at(warband.x, warband.z); - warband.faction = get_warband_faction_by_biome(warband); + if (faction == null) faction = get_warband_faction_by_biome(warband); + warband.faction = faction; spawn_warband(warband); + WarbandTracker.add(warband); } public static void load_chunks_at(int block_x, int block_z) { @@ -192,12 +218,26 @@ public class Warband { } public static void broadcast_warband(World world, String faction_key, String direction, String waypoint_key) { - IChatComponent message = new ChatComponentTranslation( - "warband.found", - new ChatComponentTranslation(faction_key).setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GOLD)), - new ChatComponentText(direction).setChatStyle(new ChatStyle().setColor(EnumChatFormatting.YELLOW)), - new ChatComponentTranslation(waypoint_key).setChatStyle(new ChatStyle().setColor(EnumChatFormatting.AQUA)) - ); + IChatComponent message; + if (waypoint_key != null && direction != null) { + message = new ChatComponentTranslation( + "warband.found", + new ChatComponentTranslation(faction_key).setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GOLD)), + new ChatComponentText(direction).setChatStyle(new ChatStyle().setColor(EnumChatFormatting.YELLOW)), + new ChatComponentTranslation(waypoint_key).setChatStyle(new ChatStyle().setColor(EnumChatFormatting.AQUA)) + ); + } else if (waypoint_key == null){ + message = new ChatComponentTranslation( + "warband.found.no_waypoint", + new ChatComponentTranslation(faction_key).setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GOLD)) + ); + } else { + message = new ChatComponentTranslation( + "warband.found.no_direction", + new ChatComponentTranslation(faction_key).setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GOLD)), + new ChatComponentTranslation(waypoint_key).setChatStyle(new ChatStyle().setColor(EnumChatFormatting.AQUA)) + ); + } LOTRSpeech.messageAllPlayersInWorld(world, message); } diff --git a/src/main/java/com/zivilon/cinder_loe/world/event/WarbandFaction.java b/src/main/java/com/zivilon/cinder_loe/world/event/WarbandFaction.java index ab410fd..2964835 100644 --- a/src/main/java/com/zivilon/cinder_loe/world/event/WarbandFaction.java +++ b/src/main/java/com/zivilon/cinder_loe/world/event/WarbandFaction.java @@ -885,6 +885,14 @@ public enum WarbandFaction { } } + public static WarbandFaction get_warband_by_name(String name) { + for (WarbandFaction faction : values()) { + if (faction.name().equals(name)) + return faction; + } + return null; + } + public static class Troop { public Class entity_class; public int amount; diff --git a/src/main/java/com/zivilon/cinder_loe/world/event/WarbandLocationInfo.java b/src/main/java/com/zivilon/cinder_loe/world/event/WarbandLocationInfo.java new file mode 100644 index 0000000..741af51 --- /dev/null +++ b/src/main/java/com/zivilon/cinder_loe/world/event/WarbandLocationInfo.java @@ -0,0 +1,13 @@ +package com.zivilon.cinder_loe.world.event; + +public class WarbandLocationInfo { + public Warband warband; + public double x; + public double z; + + public WarbandLocationInfo(Warband warband, double x, double z) { + this.warband = warband; + this.x = x; + this.z = z; + } +} diff --git a/src/main/java/com/zivilon/cinder_loe/world/event/WarbandTickHandler.java b/src/main/java/com/zivilon/cinder_loe/world/event/WarbandTickHandler.java index 57d87ff..1378811 100644 --- a/src/main/java/com/zivilon/cinder_loe/world/event/WarbandTickHandler.java +++ b/src/main/java/com/zivilon/cinder_loe/world/event/WarbandTickHandler.java @@ -7,8 +7,7 @@ import cpw.mods.fml.common.gameevent.TickEvent.ServerTickEvent; public class WarbandTickHandler { public int tick_counter = 0; -// public static int INTERVAL_TICKS = 12000; // 10 minutes at 20 TPS - public static int INTERVAL_TICKS = 1200; // 1 minutes at 20 TPS + public static int INTERVAL_TICKS = 12000; // 10 minutes at 20 TPS @SubscribeEvent public void onServerTick(ServerTickEvent event) { @@ -22,10 +21,8 @@ public class WarbandTickHandler { } public void run_task() { - System.out.println("Warband ticked"); - if (Warband.last_warband_timestamp > (System.currentTimeMillis() / 1000L) - 7200) return; // Do not spawn warband if less than 2 hours since last one -// if (Warband.random.nextInt(10) != 0) return; - System.out.println("Warband starting"); + if (Warband.last_warband_timestamp > (System.currentTimeMillis() / 1000L) - (60*60*4)) return; // Do not spawn warband if less than 4 hours since last one + if (Warband.random.nextInt(10) != 0) return; Warband.initialize_warband(); } } diff --git a/src/main/java/com/zivilon/cinder_loe/world/event/WarbandTracker.java b/src/main/java/com/zivilon/cinder_loe/world/event/WarbandTracker.java new file mode 100644 index 0000000..19928be --- /dev/null +++ b/src/main/java/com/zivilon/cinder_loe/world/event/WarbandTracker.java @@ -0,0 +1,30 @@ +package com.zivilon.cinder_loe.world.event; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class WarbandTracker { + public static Map locations = new HashMap<>(); + + public static void clear_locations() { + locations.clear(); + } + + public static void add(Warband warband) { + locations.put(warband.warband_uuid, new WarbandLocationInfo(warband, warband.x, warband.z)); + } + public static void add(WarbandLocationInfo info) { + locations.put(info.warband.warband_uuid, info); + } + + public static void remove(UUID uuid) { + locations.remove(uuid); + } + + public static List get_all() { + return new ArrayList<>(locations.values()); + } +} diff --git a/src/main/resources/assets/cinder_loe/lang/en_US.lang b/src/main/resources/assets/cinder_loe/lang/en_US.lang index f51ae63..ee8a41d 100644 --- a/src/main/resources/assets/cinder_loe/lang/en_US.lang +++ b/src/main/resources/assets/cinder_loe/lang/en_US.lang @@ -361,7 +361,11 @@ lotr.unitinfo.Rhudaur=To Hire this unit you must have the Rhudaur Objective comp lotr.unitinfo.Dale=To Hire this unit you must have the Dalish Objective complete. lotr.unitinfo.Lindon=To Hire this unit you must have the Lindon Objective complete. -warband.found=Warband of %s has been found %s of %s +warband.found=Warband of %s was spotted %s of %s! +warband.found.no_direction=Warband of %s was spotted by %s! +warband.found.no_waypoint=Warband of %s has been found! +warband.defeated.faction=Warband of %s has been defeated! +warband.defeated.no_faction=Warband has been defeated! warband.fac.MORGUL_VALE=Morgul Vale warband.fac.WOOD_ELF_SCOUT=Woodland Realm scouts warband.fac.RED_MOUNTAINS=Red Mountains diff --git a/src/main/resources/mixins.cinder_loe.json b/src/main/resources/mixins.cinder_loe.json index 755791d..cd98861 100644 --- a/src/main/resources/mixins.cinder_loe.json +++ b/src/main/resources/mixins.cinder_loe.json @@ -51,7 +51,9 @@ "MixinLOTREntityAIAttackOnCollide", "MixinLOTREntityNPC", "MixinFoodStats", - "MixinLOTRItemMug" + "MixinLOTRItemMug", + "MixinLOTRGuiMap", + "MixinLOTREntityAIOrcSkirmish" ], "client": [] }