From 8fae8beb080e647846912918a09da9c2c7a40f55 Mon Sep 17 00:00:00 2001 From: Cayden Date: Tue, 30 Oct 2018 23:01:52 -0400 Subject: [PATCH 01/40] Readded craft handlers and slight changes to argument --- .gitignore | 1 + ...entQuitFromCraftingItemImplementation.java | 146 ++++++++++++++++ .../RewardForCraftingItemImplementation.java | 158 ++++++++++++++++++ Schemas/MissionHandlers.xsd | 74 +++++--- Schemas/MissionHandlers.xsd.in | 71 ++++++-- 5 files changed, 413 insertions(+), 37 deletions(-) create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java mode change 100755 => 100644 Schemas/MissionHandlers.xsd diff --git a/.gitignore b/.gitignore index 13c0b2fbe..6c93dde3c 100755 --- a/.gitignore +++ b/.gitignore @@ -167,6 +167,7 @@ ClientBin/ *.pfx *.publishsettings node_modules/ +.DS_Store # RIA/Silverlight projects Generated_Code/ diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java new file mode 100644 index 000000000..878cb3de9 --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java @@ -0,0 +1,146 @@ +package com.microsoft.Malmo.MissionHandlers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; + +import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; +import com.microsoft.Malmo.MissionHandlers.RewardForItemBase.ItemMatcher; +import com.microsoft.Malmo.Schemas.AgentQuitFromCraftingItem; +import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithDescription; +import com.microsoft.Malmo.Schemas.MissionInit; + +/** + * + * @author Cayden Codel, Carnegie Mellon University + * + * Gives agents rewards when items are crafted. + * + */ +public class AgentQuitFromCraftingItemImplementation extends HandlerBase implements IWantToQuit { + + private AgentQuitFromCraftingItem params; + private HashMap craftedItems; + private List matchers; + private String quitCode = ""; + boolean wantToQuit = false; + boolean callCraft = true; + + public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { + String description; + + ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { + super(spec); + this.description = spec.getDescription(); + } + + String description() { + return this.description; + } + } + + @Override + public boolean parseParameters(Object params) { + if (params == null || !(params instanceof AgentQuitFromCraftingItem)) + return false; + + this.params = (AgentQuitFromCraftingItem) params; + this.matchers = new ArrayList(); + for (BlockOrItemSpecWithDescription bs : this.params.getItem()) + this.matchers.add(new ItemQuitMatcher(bs)); + return true; + } + + @Override + public boolean doIWantToQuit(MissionInit missionInit) { + return this.wantToQuit; + } + + @Override + public String getOutcome() { + return this.quitCode; + } + + @Override + public void prepare(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.register(this); + craftedItems = new HashMap(); + } + + @Override + public void cleanup() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { + if (callCraft) + checkForMatch(event.crafting); + + callCraft = !callCraft; + } + + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); + else + return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName()); + + } + + private void addCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getUnlocalizedName())); + craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + } else { + int prev = (craftedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName())); + craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + } + + private void checkForMatch(ItemStack is) { + int savedCrafted = getCraftedItemCount(is); + if (is != null && is.getItem() != null) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedCrafted != 0) { + if (is.getCount() + savedCrafted >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } + } + + addCraftedItemCount(is); + } + } +} diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java new file mode 100644 index 000000000..522bd6752 --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java @@ -0,0 +1,158 @@ +package com.microsoft.Malmo.MissionHandlers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import com.microsoft.Malmo.MalmoMod; +import com.microsoft.Malmo.MalmoMod.IMalmoMessageListener; +import com.microsoft.Malmo.MalmoMod.MalmoMessageType; +import com.microsoft.Malmo.MissionHandlerInterfaces.IRewardProducer; +import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithReward; +import com.microsoft.Malmo.Schemas.MissionInit; +import com.microsoft.Malmo.Schemas.RewardForCraftingItem; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; + +/** + * + * @author Cayden Codel, Carnegie Mellon University + * + * Sends a reward when the agent crafts the specified item with + * specified amounts. + */ +public class RewardForCraftingItemImplementation extends RewardForItemBase + implements IRewardProducer, IMalmoMessageListener { + + private RewardForCraftingItem params; + private ArrayList matchers; + private HashMap craftedItems; + boolean callCraft = true; + + @SubscribeEvent + public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { + if (callCraft) + checkForMatch(event.crafting); + + callCraft = !callCraft; + } + + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); + else + return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName()); + + } + + private void addCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getUnlocalizedName())); + craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + } else { + int prev = (craftedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName())); + craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + } + + private void checkForMatch(ItemStack is) { + int savedCrafted = getCraftedItemCount(is); + if (is != null && is.getItem() != null) { + for (ItemMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (!params.isSparse()) { + if (savedCrafted != 0 && savedCrafted < matcher.matchSpec.getAmount()) { + for (int i = savedCrafted; i < matcher.matchSpec.getAmount() + && i - savedCrafted < is.getCount(); i++) + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + + } else if (savedCrafted != 0 && savedCrafted >= matcher.matchSpec.getAmount()) { + // Do nothing + } else { + for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + + } + } else { + if (savedCrafted < matcher.matchSpec.getAmount() + && savedCrafted + is.getCount() >= matcher.matchSpec.getAmount()) + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } + + addCraftedItemCount(is); + } + + } + + @Override + public boolean parseParameters(Object params) { + if (params == null || !(params instanceof RewardForCraftingItem)) + return false; + + matchers = new ArrayList(); + + this.params = (RewardForCraftingItem) params; + for (BlockOrItemSpecWithReward spec : this.params.getItem()) + this.matchers.add(new ItemMatcher(spec)); + + return true; + } + + @Override + public void prepare(MissionInit missionInit) { + super.prepare(missionInit); + MinecraftForge.EVENT_BUS.register(this); + MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + craftedItems = new HashMap(); + } + + @Override + public void getReward(MissionInit missionInit, MultidimensionalReward reward) { + super.getReward(missionInit, reward); + } + + @Override + public void cleanup() { + super.cleanup(); + MinecraftForge.EVENT_BUS.unregister(this); + MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + } + + @Override + public void onMessage(MalmoMessageType messageType, Map data) { + } +} diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd old mode 100755 new mode 100644 index a0171f2bd..51ec0e3ef --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -139,28 +139,28 @@ - + - Loads a saved world from disk. You can find the saved worlds in "{{{Minecraft\run\saves}}}". Use the full path to one of those folders. - - If Minecraft is running on a different machine then copy the folder to a readable network location and update the path accordingly. Example: - - {{{<FileWorldGenerator src="\\\\machine-id\\shared\\ProjectMalmo\\saved_maps\\arena" />}}} + Generates a survival world with the specified biome. - + - The path to the saved world folder. + The biome type for the world. Each chunk will be loaded with the biome specified. + + If left blank, the world will be a normal survival world. + + Biome ID #'s can be found here: https://minecraft.gamepedia.com/Biome#Biome_IDs - Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested source filename). + Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested seed). Force reloading is slow, but will guarantee that no world changes will carry over between missions. @@ -176,28 +176,28 @@ - + - Generates a survival world with the specified biome. + Loads a saved world from disk. You can find the saved worlds in "{{{Minecraft\run\saves}}}". Use the full path to one of those folders. + + If Minecraft is running on a different machine then copy the folder to a readable network location and update the path accordingly. Example: + + {{{<FileWorldGenerator src="\\\\machine-id\\shared\\ProjectMalmo\\saved_maps\\arena" />}}} - + - The biome type for the world. Each chunk will be loaded with the biome specified. - - If left blank, the world will be a normal survival world. - - Biome ID #'s can be found here: https://minecraft.gamepedia.com/Biome#Biome_IDs + The path to the saved world folder. - Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested seed). + Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested source filename). Force reloading is slow, but will guarantee that no world changes will carry over between missions. @@ -1032,7 +1032,9 @@ Sets whether or not the compass location should be randomized within a certain radius. + If false, will set the compass location to the block that was randomly placed. + If true, will set the compass location to a random spot within the radius specified below. @@ -1636,6 +1638,7 @@ + @@ -2008,7 +2011,6 @@ - @@ -2105,12 +2107,14 @@ + + @@ -2212,6 +2216,25 @@ + + + + Sends a reward when the agent crafts a specific item. + + If Sparse is set to true, will only give full reward on crafting of entire amount. + + Otherwise, will give the reward amount notated for each item crafted up to the amount noted. + + + + + + + + + + + @@ -2471,6 +2494,19 @@ + + + + When this is included the agent's mission will end when they craft a specified item. + + + + + + + + + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index 4e3bc543f..9d72d92ae 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -139,28 +139,28 @@ - + - Loads a saved world from disk. You can find the saved worlds in "{{{Minecraft\run\saves}}}". Use the full path to one of those folders. - - If Minecraft is running on a different machine then copy the folder to a readable network location and update the path accordingly. Example: - - {{{<FileWorldGenerator src="\\\\machine-id\\shared\\ProjectMalmo\\saved_maps\\arena" />}}} + Generates a survival world with the specified biome. - + - The path to the saved world folder. + The biome type for the world. Each chunk will be loaded with the biome specified. + + If left blank, the world will be a normal survival world. + + Biome ID #'s can be found here: https://minecraft.gamepedia.com/Biome#Biome_IDs - Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested source filename). + Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested seed). Force reloading is slow, but will guarantee that no world changes will carry over between missions. @@ -176,28 +176,28 @@ - + - Generates a survival world with the specified biome. + Loads a saved world from disk. You can find the saved worlds in "{{{Minecraft\run\saves}}}". Use the full path to one of those folders. + + If Minecraft is running on a different machine then copy the folder to a readable network location and update the path accordingly. Example: + + {{{<FileWorldGenerator src="\\\\machine-id\\shared\\ProjectMalmo\\saved_maps\\arena" />}}} - + - The biome type for the world. Each chunk will be loaded with the biome specified. - - If left blank, the world will be a normal survival world. - - Biome ID #'s can be found here: https://minecraft.gamepedia.com/Biome#Biome_IDs + The path to the saved world folder. - Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested seed). + Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested source filename). Force reloading is slow, but will guarantee that no world changes will carry over between missions. @@ -1638,6 +1638,7 @@ + @@ -2106,12 +2107,14 @@ + + @@ -2213,6 +2216,25 @@ + + + + Sends a reward when the agent crafts a specific item. + + If Sparse is set to true, will only give full reward on crafting of entire amount. + + Otherwise, will give the reward amount notated for each item crafted up to the amount noted. + + + + + + + + + + + @@ -2472,6 +2494,19 @@ + + + + When this is included the agent's mission will end when they craft a specified item. + + + + + + + + + From 8d5f166214ffcdad7c5d7f06c7062be2284f79ec Mon Sep 17 00:00:00 2001 From: ccodel Date: Thu, 6 Dec 2018 16:29:57 -0500 Subject: [PATCH 02/40] Reimplemented craft, collect handlers, added possess handler with decrement --- ...tQuitFromCollectingItemImplementation.java | 229 +++++++++++------- ...tQuitFromPossessingItemImplementation.java | 179 ++++++++++++++ .../RewardForCraftingItemImplementation.java | 19 +- Schemas/Mission.xsd | 3 + Schemas/Mission.xsd.in | 3 + Schemas/MissionHandlers.xsd | 13 + Schemas/MissionHandlers.xsd.in | 13 + 7 files changed, 366 insertions(+), 93 deletions(-) create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java mode change 100755 => 100644 Schemas/Mission.xsd diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java index 42b37c887..0300760c7 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java @@ -1,107 +1,156 @@ package com.microsoft.Malmo.MissionHandlers; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import net.minecraft.item.ItemStack; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.EntityItemPickupEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; +import com.microsoft.Malmo.MissionHandlers.AgentQuitFromCraftingItemImplementation.ItemQuitMatcher; import com.microsoft.Malmo.MissionHandlers.RewardForCollectingItemImplementation.GainItemEvent; +import com.microsoft.Malmo.MissionHandlers.RewardForItemBase.ItemMatcher; import com.microsoft.Malmo.Schemas.AgentQuitFromCollectingItem; import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithDescription; import com.microsoft.Malmo.Schemas.MissionInit; -public class AgentQuitFromCollectingItemImplementation extends HandlerBase implements IWantToQuit -{ - AgentQuitFromCollectingItem params; - List matchers; - String quitCode = ""; - boolean wantToQuit = false; - - public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher - { - String description; - - ItemQuitMatcher(BlockOrItemSpecWithDescription spec) - { - super(spec); - this.description = spec.getDescription(); - } - - String description() - { - return this.description; - } - } - - @Override - public boolean parseParameters(Object params) - { - if (params == null || !(params instanceof AgentQuitFromCollectingItem)) - return false; - - this.params = (AgentQuitFromCollectingItem)params; - this.matchers = new ArrayList(); - for (BlockOrItemSpecWithDescription bs : this.params.getItem()) - this.matchers.add(new ItemQuitMatcher(bs)); - return true; - } - - @Override - public boolean doIWantToQuit(MissionInit missionInit) - { - return this.wantToQuit; - } - - @Override - public String getOutcome() - { - return this.quitCode; - } - - @Override - public void prepare(MissionInit missionInit) - { - MinecraftForge.EVENT_BUS.register(this); - } - - @Override - public void cleanup() - { - MinecraftForge.EVENT_BUS.unregister(this); - } - - @SubscribeEvent - public void onGainItem(GainItemEvent event) - { - checkForMatch(event.stack); - } - - @SubscribeEvent - public void onPickupItem(EntityItemPickupEvent event) - { - if (event.getItem() != null && event.getItem().getEntityItem() != null) - { - ItemStack stack = event.getItem().getEntityItem(); - checkForMatch(stack); - } - } - - private void checkForMatch(ItemStack is) - { - if (is != null) - { - for (ItemQuitMatcher matcher : this.matchers) - { - if (matcher.matches(is)) - { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } - } - } +public class AgentQuitFromCollectingItemImplementation extends HandlerBase implements IWantToQuit { + AgentQuitFromCollectingItem params; + private HashMap collectedItems; + List matchers; + String quitCode = ""; + boolean wantToQuit = false; + boolean callCraft = true; + + public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { + String description; + + ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { + super(spec); + this.description = spec.getDescription(); + } + + String description() { + return this.description; + } + } + + @Override + public boolean parseParameters(Object params) { + if (params == null || !(params instanceof AgentQuitFromCollectingItem)) + return false; + + this.params = (AgentQuitFromCollectingItem) params; + this.matchers = new ArrayList(); + for (BlockOrItemSpecWithDescription bs : this.params.getItem()) + this.matchers.add(new ItemQuitMatcher(bs)); + return true; + } + + @Override + public boolean doIWantToQuit(MissionInit missionInit) { + return this.wantToQuit; + } + + @Override + public String getOutcome() { + return this.quitCode; + } + + @Override + public void prepare(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.register(this); + collectedItems = new HashMap(); + } + + @Override + public void cleanup() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void onGainItem(GainItemEvent event) { + System.out.println("Gained an item: " + event.stack.getUnlocalizedName()); + checkForMatch(event.stack); + } + + @SubscribeEvent + public void onPickupItem(EntityItemPickupEvent event) { + if (event.getItem() != null && event.getItem().getEntityItem() != null) { + ItemStack stack = event.getItem().getEntityItem(); + checkForMatch(stack); + } + } + + @SubscribeEvent + public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { + if (callCraft) + checkForMatch(event.crafting); + + callCraft = !callCraft; + } + + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getUnlocalizedName()); + else + return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName()); + + } + + private void addCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + } else { + int prev = (collectedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName())); + collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + } + + private void checkForMatch(ItemStack is) { + int savedCrafted = getCraftedItemCount(is); + if (is != null && is.getItem() != null) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedCrafted != 0) { + if (is.getCount() + savedCrafted >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } + } + + addCollectedItemCount(is); + } + } } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java new file mode 100644 index 000000000..380e2f928 --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java @@ -0,0 +1,179 @@ +package com.microsoft.Malmo.MissionHandlers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.player.EntityItemPickupEvent; +import net.minecraftforge.event.entity.item.ItemTossEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; +import com.microsoft.Malmo.MissionHandlers.AgentQuitFromCraftingItemImplementation.ItemQuitMatcher; +import com.microsoft.Malmo.MissionHandlers.RewardForCollectingItemImplementation.GainItemEvent; +import com.microsoft.Malmo.MissionHandlers.RewardForItemBase.ItemMatcher; +import com.microsoft.Malmo.Schemas.AgentQuitFromPossessingItem; +import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithDescription; +import com.microsoft.Malmo.Schemas.MissionInit; + +public class AgentQuitFromPossessingItemImplementation extends HandlerBase implements IWantToQuit { + AgentQuitFromPossessingItem params; + private HashMap collectedItems; + List matchers; + String quitCode = ""; + boolean wantToQuit = false; + boolean callCraft = true; + + public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { + String description; + + ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { + super(spec); + this.description = spec.getDescription(); + } + + String description() { + return this.description; + } + } + + @Override + public boolean parseParameters(Object params) { + if (params == null || !(params instanceof AgentQuitFromPossessingItem)) + return false; + + this.params = (AgentQuitFromPossessingItem) params; + this.matchers = new ArrayList(); + for (BlockOrItemSpecWithDescription bs : this.params.getItem()) + this.matchers.add(new ItemQuitMatcher(bs)); + return true; + } + + @Override + public boolean doIWantToQuit(MissionInit missionInit) { + return this.wantToQuit; + } + + @Override + public String getOutcome() { + return this.quitCode; + } + + @Override + public void prepare(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.register(this); + collectedItems = new HashMap(); + } + + @Override + public void cleanup() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void onGainItem(GainItemEvent event) { + System.out.println("Gained an item: " + event.stack.getUnlocalizedName()); + checkForMatch(event.stack); + } + + @SubscribeEvent + public void onPickupItem(EntityItemPickupEvent event) { + if (event.getItem() != null && event.getItem().getEntityItem() != null) { + ItemStack stack = event.getItem().getEntityItem(); + checkForMatch(stack); + } + } + + @SubscribeEvent + public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { + if (callCraft) + checkForMatch(event.crafting); + + callCraft = !callCraft; + } + + @SubscribeEvent + public void onItemToss(ItemTossEvent event) { + if (event.getEntityItem() != null && event.getEntityItem().getEntityItem() != null) { + ItemStack stack = event.getEntityItem().getEntityItem(); + removeCollectedItem(stack); + } + } + + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getUnlocalizedName()); + else + return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName()); + + } + + private void addCollectedItem(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + } else { + int prev = (collectedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName())); + collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + } + + private void removeCollectedItem(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + collectedItems.put(is.getUnlocalizedName(), Integer.max(0, prev - is.getCount())); + } else { + int prev = (collectedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName())); + collectedItems.put(is.getItem().getUnlocalizedName(), Integer.max(0, prev - is.getCount())); + } + } + + private void checkForMatch(ItemStack is) { + int savedCrafted = getCraftedItemCount(is); + if (is != null && is.getItem() != null) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedCrafted != 0) { + if (is.getCount() + savedCrafted >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } + } + + addCollectedItem(is); + } + } +} diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java index 522bd6752..8329fddd6 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java @@ -79,36 +79,49 @@ private void addCraftedItemCount(ItemStack is) { } private void checkForMatch(ItemStack is) { + //System.out.println("Checking for match on " + is.getItem().getUnlocalizedName()); int savedCrafted = getCraftedItemCount(is); + //System.out.println("Previous saved amount is " + savedCrafted); if (is != null && is.getItem() != null) { for (ItemMatcher matcher : this.matchers) { if (matcher.matches(is)) { if (!params.isSparse()) { if (savedCrafted != 0 && savedCrafted < matcher.matchSpec.getAmount()) { for (int i = savedCrafted; i < matcher.matchSpec.getAmount() - && i - savedCrafted < is.getCount(); i++) + && i - savedCrafted < is.getCount(); i++) { + //System.out.println("Sparse, had nonzero saved crafted amount, giving a reward of " + // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); this.adjustAndDistributeReward( ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), params.getDimension(), ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } } else if (savedCrafted != 0 && savedCrafted >= matcher.matchSpec.getAmount()) { // Do nothing + //System.out + // .println("Sparse, had nonzero saved crafted amount, but not enough new for reward"); } else { - for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) + for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { + //System.out.println("Had zero saved crafted amount, giving a reward of " + // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); this.adjustAndDistributeReward( ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), params.getDimension(), ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } } } else { if (savedCrafted < matcher.matchSpec.getAmount() - && savedCrafted + is.getCount() >= matcher.matchSpec.getAmount()) + && savedCrafted + is.getCount() >= matcher.matchSpec.getAmount()) { + //System.out.println("Not sparse, giving a reward of " + // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); this.adjustAndDistributeReward( ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), params.getDimension(), ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } } } } diff --git a/Schemas/Mission.xsd b/Schemas/Mission.xsd old mode 100755 new mode 100644 index 290d40590..c77f86969 --- a/Schemas/Mission.xsd +++ b/Schemas/Mission.xsd @@ -353,6 +353,7 @@ + @@ -376,6 +377,8 @@ + + diff --git a/Schemas/Mission.xsd.in b/Schemas/Mission.xsd.in index 1048707b1..00f9ef7fa 100644 --- a/Schemas/Mission.xsd.in +++ b/Schemas/Mission.xsd.in @@ -353,6 +353,7 @@ + @@ -376,6 +377,8 @@ + + diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd index 51ec0e3ef..30a44514e 100644 --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -2506,6 +2506,19 @@ + + + + + When this is included the agent's mission will end when they possess the specified item in their inventory all at once. + + + + + + + + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index 9d72d92ae..935a39f4f 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -2506,6 +2506,19 @@ + + + + + When this is included the agent's mission will end when they possess the specified item in their inventory all at once. + + + + + + + + From 230f49b6f28ed4aad4aafb7db80c24f2b11e5462 Mon Sep 17 00:00:00 2001 From: ccodel Date: Tue, 5 Feb 2019 21:39:17 -0500 Subject: [PATCH 03/40] Added smelting reward and quit handlers --- ...entQuitFromSmeltingItemImplementation.java | 146 +++++++++++++++ .../RewardForSmeltingItemImplementation.java | 171 ++++++++++++++++++ Schemas/Mission.xsd | 2 + Schemas/Mission.xsd.in | 2 + Schemas/MissionEnded.xsd | 0 Schemas/MissionHandlers.xsd | 32 ++++ Schemas/MissionHandlers.xsd.in | 32 ++++ Schemas/MissionInit.xsd | 0 Schemas/Types.xsd | 0 9 files changed, 385 insertions(+) create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java mode change 100755 => 100644 Schemas/MissionEnded.xsd mode change 100755 => 100644 Schemas/MissionInit.xsd mode change 100755 => 100644 Schemas/Types.xsd diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java new file mode 100644 index 000000000..9ebc9caf6 --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java @@ -0,0 +1,146 @@ +package com.microsoft.Malmo.MissionHandlers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; + +import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; +import com.microsoft.Malmo.MissionHandlers.RewardForItemBase.ItemMatcher; +import com.microsoft.Malmo.Schemas.AgentQuitFromSmeltingItem; +import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithDescription; +import com.microsoft.Malmo.Schemas.MissionInit; + +/** + * + * @author Cayden Codel, Carnegie Mellon University + * + * Gives agents rewards when items are smelted. + * + */ +public class AgentQuitFromSmeltingItemImplementation extends HandlerBase implements IWantToQuit { + + private AgentQuitFromSmeltingItem params; + private HashMap smeltedItems; + private List matchers; + private String quitCode = ""; + boolean wantToQuit = false; + boolean callSmelt = true; + + public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { + String description; + + ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { + super(spec); + this.description = spec.getDescription(); + } + + String description() { + return this.description; + } + } + + @Override + public boolean parseParameters(Object params) { + if (params == null || !(params instanceof AgentQuitFromSmeltingItem)) + return false; + + this.params = (AgentQuitFromSmeltingItem) params; + this.matchers = new ArrayList(); + for (BlockOrItemSpecWithDescription bs : this.params.getItem()) + this.matchers.add(new ItemQuitMatcher(bs)); + return true; + } + + @Override + public boolean doIWantToQuit(MissionInit missionInit) { + return this.wantToQuit; + } + + @Override + public String getOutcome() { + return this.quitCode; + } + + @Override + public void prepare(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.register(this); + smeltedItems = new HashMap(); + } + + @Override + public void cleanup() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { + if (callSmelt) + checkForMatch(event.smelting); + + callSmelt = !callSmelt; + } + + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getSmeltedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (smeltedItems.get(is.getUnlocalizedName()) == null) ? 0 : smeltedItems.get(is.getUnlocalizedName()); + else + return (smeltedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : smeltedItems.get(is.getItem().getUnlocalizedName()); + + } + + private void addSmeltedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (smeltedItems.get(is.getUnlocalizedName()) == null ? 0 + : smeltedItems.get(is.getUnlocalizedName())); + smeltedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + } else { + int prev = (smeltedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : smeltedItems.get(is.getItem().getUnlocalizedName())); + smeltedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + } + + private void checkForMatch(ItemStack is) { + int savedSmelted = getSmeltedItemCount(is); + if (is != null && is.getItem() != null) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedSmelted != 0) { + if (is.getCount() + savedSmelted >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } + } + + addSmeltedItemCount(is); + } + } +} diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java new file mode 100644 index 000000000..ee4a5fded --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java @@ -0,0 +1,171 @@ +package com.microsoft.Malmo.MissionHandlers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import com.microsoft.Malmo.MalmoMod; +import com.microsoft.Malmo.MalmoMod.IMalmoMessageListener; +import com.microsoft.Malmo.MalmoMod.MalmoMessageType; +import com.microsoft.Malmo.MissionHandlerInterfaces.IRewardProducer; +import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithReward; +import com.microsoft.Malmo.Schemas.MissionInit; +import com.microsoft.Malmo.Schemas.RewardForSmeltingItem; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; + +/** + * + * @author Cayden Codel, Carnegie Mellon University + * + * Sends a reward when the agent smelts the specified item with + * specified amounts. + */ +public class RewardForSmeltingItemImplementation extends RewardForItemBase + implements IRewardProducer, IMalmoMessageListener { + + private RewardForSmeltingItem params; + private ArrayList matchers; + private HashMap smeltedItems; + boolean callSmelt = true; + + @SubscribeEvent + public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { + if (callSmelt) + checkForMatch(event.smelting); + + callSmelt = !callSmelt; + } + + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (smeltedItems.get(is.getUnlocalizedName()) == null) ? 0 : smeltedItems.get(is.getUnlocalizedName()); + else + return (smeltedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : smeltedItems.get(is.getItem().getUnlocalizedName()); + + } + + private void addSmeltedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (smeltedItems.get(is.getUnlocalizedName()) == null ? 0 + : smeltedItems.get(is.getUnlocalizedName())); + smeltedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + } else { + int prev = (smeltedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : smeltedItems.get(is.getItem().getUnlocalizedName())); + smeltedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + } + + private void checkForMatch(ItemStack is) { + //System.out.println("Checking for match on " + is.getItem().getUnlocalizedName()); + int savedCrafted = getCraftedItemCount(is); + //System.out.println("Previous saved amount is " + savedCrafted); + if (is != null && is.getItem() != null) { + for (ItemMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (!params.isSparse()) { + if (savedCrafted != 0 && savedCrafted < matcher.matchSpec.getAmount()) { + for (int i = savedCrafted; i < matcher.matchSpec.getAmount() + && i - savedCrafted < is.getCount(); i++) { + //System.out.println("Sparse, had nonzero saved crafted amount, giving a reward of " + // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + + } else if (savedCrafted != 0 && savedCrafted >= matcher.matchSpec.getAmount()) { + // Do nothing + //System.out + // .println("Sparse, had nonzero saved crafted amount, but not enough new for reward"); + } else { + for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { + //System.out.println("Had zero saved crafted amount, giving a reward of " + // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + + } + } else { + if (savedCrafted < matcher.matchSpec.getAmount() + && savedCrafted + is.getCount() >= matcher.matchSpec.getAmount()) { + //System.out.println("Not sparse, giving a reward of " + // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } + } + + addSmeltedItemCount(is); + } + + } + + @Override + public boolean parseParameters(Object params) { + if (params == null || !(params instanceof RewardForSmeltingItem)) + return false; + + matchers = new ArrayList(); + + this.params = (RewardForSmeltingItem) params; + for (BlockOrItemSpecWithReward spec : this.params.getItem()) + this.matchers.add(new ItemMatcher(spec)); + + return true; + } + + @Override + public void prepare(MissionInit missionInit) { + super.prepare(missionInit); + MinecraftForge.EVENT_BUS.register(this); + MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + smeltedItems = new HashMap(); + } + + @Override + public void getReward(MissionInit missionInit, MultidimensionalReward reward) { + super.getReward(missionInit, reward); + } + + @Override + public void cleanup() { + super.cleanup(); + MinecraftForge.EVENT_BUS.unregister(this); + MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + } + + @Override + public void onMessage(MalmoMessageType messageType, Map data) { + } +} diff --git a/Schemas/Mission.xsd b/Schemas/Mission.xsd index c77f86969..fdfd15e5d 100644 --- a/Schemas/Mission.xsd +++ b/Schemas/Mission.xsd @@ -354,6 +354,7 @@ + @@ -378,6 +379,7 @@ + diff --git a/Schemas/Mission.xsd.in b/Schemas/Mission.xsd.in index 00f9ef7fa..b9cb213b8 100644 --- a/Schemas/Mission.xsd.in +++ b/Schemas/Mission.xsd.in @@ -354,6 +354,7 @@ + @@ -378,6 +379,7 @@ + diff --git a/Schemas/MissionEnded.xsd b/Schemas/MissionEnded.xsd old mode 100755 new mode 100644 diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd index 30a44514e..509ee37fb 100644 --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -2234,6 +2234,25 @@ + + + + + Sends a reward when the agent smelts a specific item. + + If Sparse is set to true, will only give full reward on crafting of entire amount. + + Otherwise, will give the reward amount notated for each item crafted up to the amount noted. + + + + + + + + + + @@ -2507,6 +2526,19 @@ + + + + When this is included the agent's mission will end when they smelt a specified item. + + + + + + + + + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index 935a39f4f..b777dcd20 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -2234,6 +2234,25 @@ + + + + + Sends a reward when the agent smelts a specific item. + + If Sparse is set to true, will only give full reward on crafting of entire amount. + + Otherwise, will give the reward amount notated for each item crafted up to the amount noted. + + + + + + + + + + @@ -2507,6 +2526,19 @@ + + + + When this is included the agent's mission will end when they smelt a specified item. + + + + + + + + + diff --git a/Schemas/MissionInit.xsd b/Schemas/MissionInit.xsd old mode 100755 new mode 100644 diff --git a/Schemas/Types.xsd b/Schemas/Types.xsd old mode 100755 new mode 100644 From f1cf5d6adab6ea8f8ea72d226eb46459b728d907 Mon Sep 17 00:00:00 2001 From: ccodel Date: Fri, 8 Feb 2019 22:25:08 -0500 Subject: [PATCH 04/40] Bulk of implementation done, onto testing --- ...tQuitFromCollectingItemImplementation.java | 270 ++++++++-------- ...entQuitFromCraftingItemImplementation.java | 35 +-- ...tQuitFromPossessingItemImplementation.java | 125 ++++---- ...entQuitFromSmeltingItemImplementation.java | 252 +++++++-------- ...RewardForCollectingItemImplementation.java | 226 +++++++++----- .../RewardForCraftingItemImplementation.java | 287 +++++++++--------- ...RewardForPossessingItemImplementation.java | 232 ++++++++++++++ .../RewardForSmeltingItemImplementation.java | 79 +++-- Schemas/Mission.xsd | 3 +- Schemas/Mission.xsd.in | 3 +- Schemas/MissionHandlers.xsd | 28 +- Schemas/MissionHandlers.xsd.in | 28 +- 12 files changed, 955 insertions(+), 613 deletions(-) create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForPossessingItemImplementation.java diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java index 0300760c7..ab8f95b4e 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java @@ -7,150 +7,144 @@ import net.minecraft.item.ItemStack; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.EntityItemPickupEvent; -import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; -import com.microsoft.Malmo.MissionHandlers.AgentQuitFromCraftingItemImplementation.ItemQuitMatcher; import com.microsoft.Malmo.MissionHandlers.RewardForCollectingItemImplementation.GainItemEvent; -import com.microsoft.Malmo.MissionHandlers.RewardForItemBase.ItemMatcher; import com.microsoft.Malmo.Schemas.AgentQuitFromCollectingItem; import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithDescription; import com.microsoft.Malmo.Schemas.MissionInit; +/** + * Quits the mission when the agent has collected the right amount of items. The count on the item collection is absolute. + */ public class AgentQuitFromCollectingItemImplementation extends HandlerBase implements IWantToQuit { - AgentQuitFromCollectingItem params; - private HashMap collectedItems; - List matchers; - String quitCode = ""; - boolean wantToQuit = false; - boolean callCraft = true; - - public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { - String description; - - ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { - super(spec); - this.description = spec.getDescription(); - } - - String description() { - return this.description; - } - } - - @Override - public boolean parseParameters(Object params) { - if (params == null || !(params instanceof AgentQuitFromCollectingItem)) - return false; - - this.params = (AgentQuitFromCollectingItem) params; - this.matchers = new ArrayList(); - for (BlockOrItemSpecWithDescription bs : this.params.getItem()) - this.matchers.add(new ItemQuitMatcher(bs)); - return true; - } - - @Override - public boolean doIWantToQuit(MissionInit missionInit) { - return this.wantToQuit; - } - - @Override - public String getOutcome() { - return this.quitCode; - } - - @Override - public void prepare(MissionInit missionInit) { - MinecraftForge.EVENT_BUS.register(this); - collectedItems = new HashMap(); - } - - @Override - public void cleanup() { - MinecraftForge.EVENT_BUS.unregister(this); - } - - @SubscribeEvent - public void onGainItem(GainItemEvent event) { - System.out.println("Gained an item: " + event.stack.getUnlocalizedName()); - checkForMatch(event.stack); - } - - @SubscribeEvent - public void onPickupItem(EntityItemPickupEvent event) { - if (event.getItem() != null && event.getItem().getEntityItem() != null) { - ItemStack stack = event.getItem().getEntityItem(); - checkForMatch(stack); - } - } - - @SubscribeEvent - public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { - if (callCraft) - checkForMatch(event.crafting); - - callCraft = !callCraft; - } - - private boolean getVariant(ItemStack is) { - for (ItemMatcher matcher : matchers) { - if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { - if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) - return true; - if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) - return true; - } - } - - return false; - } - - private int getCraftedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) - return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 - : collectedItems.get(is.getUnlocalizedName()); - else - return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 - : collectedItems.get(is.getItem().getUnlocalizedName()); - - } - - private void addCollectedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) { - int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getUnlocalizedName())); - collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - } else { - int prev = (collectedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getItem().getUnlocalizedName())); - collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - } - } - - private void checkForMatch(ItemStack is) { - int savedCrafted = getCraftedItemCount(is); - if (is != null && is.getItem() != null) { - for (ItemQuitMatcher matcher : this.matchers) { - if (matcher.matches(is)) { - if (savedCrafted != 0) { - if (is.getCount() + savedCrafted >= matcher.matchSpec.getAmount()) { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } else if (is.getCount() >= matcher.matchSpec.getAmount()) { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } - } - - addCollectedItemCount(is); - } - } -} + + private AgentQuitFromCollectingItem params; + private HashMap collectedItems; + private List matchers; + private String quitCode = ""; + private boolean wantToQuit = false; + + public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { + String description; + + ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { + super(spec); + this.description = spec.getDescription(); + } + + String description() { + return this.description; + } + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof AgentQuitFromCollectingItem)) + return false; + + this.params = (AgentQuitFromCollectingItem) params; + this.matchers = new ArrayList(); + for (BlockOrItemSpecWithDescription bs : this.params.getItem()) + this.matchers.add(new ItemQuitMatcher(bs)); + return true; + } + + @Override + public boolean doIWantToQuit(MissionInit missionInit) { + return this.wantToQuit; + } + + @Override + public String getOutcome() { + return this.quitCode; + } + + @Override + public void prepare(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.register(this); + collectedItems = new HashMap(); + } + + @Override + public void cleanup() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void onGainItem(GainItemEvent event) { + checkForMatch(event.stack); + } + + @SubscribeEvent + public void onPickupItem(EntityItemPickupEvent event) { + if (event.getItem() != null) { + ItemStack stack = event.getItem().getEntityItem(); + checkForMatch(stack); + } + } + + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ + private boolean getVariant(ItemStack is) { + for (ItemQuitMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private void addCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + if (variant) + collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + else + collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + + private int getCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 : collectedItems.get(is.getUnlocalizedName()); + else + return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName()); + } + + private void checkForMatch(ItemStack is) { + int savedCollected = getCollectedItemCount(is); + if (is != null) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedCollected != 0) { + if (is.getCount() + savedCollected >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } + } + + addCollectedItemCount(is); + } + } +} \ No newline at end of file diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java index 878cb3de9..8b1b66af7 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java @@ -10,17 +10,14 @@ import net.minecraftforge.fml.common.gameevent.PlayerEvent; import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; -import com.microsoft.Malmo.MissionHandlers.RewardForItemBase.ItemMatcher; import com.microsoft.Malmo.Schemas.AgentQuitFromCraftingItem; import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithDescription; import com.microsoft.Malmo.Schemas.MissionInit; /** - * * @author Cayden Codel, Carnegie Mellon University - * - * Gives agents rewards when items are crafted. * + * Gives agents rewards when items are crafted. Handles variants and colors. */ public class AgentQuitFromCraftingItemImplementation extends HandlerBase implements IWantToQuit { @@ -28,8 +25,8 @@ public class AgentQuitFromCraftingItemImplementation extends HandlerBase impleme private HashMap craftedItems; private List matchers; private String quitCode = ""; - boolean wantToQuit = false; - boolean callCraft = true; + private boolean wantToQuit = false; + private boolean callCraft = true; public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { String description; @@ -46,7 +43,7 @@ String description() { @Override public boolean parseParameters(Object params) { - if (params == null || !(params instanceof AgentQuitFromCraftingItem)) + if (!(params instanceof AgentQuitFromCraftingItem)) return false; this.params = (AgentQuitFromCraftingItem) params; @@ -85,8 +82,16 @@ public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { callCraft = !callCraft; } + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ private boolean getVariant(ItemStack is) { - for (ItemMatcher matcher : matchers) { + for (ItemQuitMatcher matcher : matchers) { if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) return true; @@ -106,26 +111,22 @@ private int getCraftedItemCount(ItemStack is) { else return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getItem().getUnlocalizedName()); - } private void addCraftedItemCount(ItemStack is) { boolean variant = getVariant(is); - if (variant) { - int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 - : craftedItems.get(is.getUnlocalizedName())); + int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getUnlocalizedName())); + if (variant) craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - } else { - int prev = (craftedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 - : craftedItems.get(is.getItem().getUnlocalizedName())); + else craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - } } private void checkForMatch(ItemStack is) { int savedCrafted = getCraftedItemCount(is); - if (is != null && is.getItem() != null) { + if (is != null) { for (ItemQuitMatcher matcher : this.matchers) { if (matcher.matches(is)) { if (savedCrafted != 0) { diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java index 380e2f928..1629cf061 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java @@ -4,28 +4,35 @@ import java.util.HashMap; import java.util.List; +import com.microsoft.Malmo.Schemas.AgentQuitFromPossessingItem; import net.minecraft.item.ItemStack; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.entity.player.EntityItemPickupEvent; import net.minecraftforge.event.entity.item.ItemTossEvent; -import net.minecraftforge.fml.common.gameevent.PlayerEvent; +import net.minecraftforge.event.entity.player.EntityItemPickupEvent; +import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent; +import net.minecraftforge.event.world.BlockEvent.PlaceEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; -import com.microsoft.Malmo.MissionHandlers.AgentQuitFromCraftingItemImplementation.ItemQuitMatcher; import com.microsoft.Malmo.MissionHandlers.RewardForCollectingItemImplementation.GainItemEvent; -import com.microsoft.Malmo.MissionHandlers.RewardForItemBase.ItemMatcher; -import com.microsoft.Malmo.Schemas.AgentQuitFromPossessingItem; +import com.microsoft.Malmo.MissionHandlers.RewardForDiscardingItemImplementation.LoseItemEvent; import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithDescription; import com.microsoft.Malmo.Schemas.MissionInit; +/** + * @author Cayden Codel, Carnegie Mellon University + *

+ * Quits the mission when the agent has possessed the right amount of items. The count on the item collection is non-absolute. + *

+ * In order to quit the mission, the agent must have the requisite items in its inventory all at one time. + */ public class AgentQuitFromPossessingItemImplementation extends HandlerBase implements IWantToQuit { - AgentQuitFromPossessingItem params; + + private AgentQuitFromPossessingItem params; private HashMap collectedItems; - List matchers; - String quitCode = ""; - boolean wantToQuit = false; - boolean callCraft = true; + private List matchers; + private String quitCode = ""; + private boolean wantToQuit = false; public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { String description; @@ -42,7 +49,7 @@ String description() { @Override public boolean parseParameters(Object params) { - if (params == null || !(params instanceof AgentQuitFromPossessingItem)) + if (!(params instanceof AgentQuitFromPossessingItem)) return false; this.params = (AgentQuitFromPossessingItem) params; @@ -75,36 +82,49 @@ public void cleanup() { @SubscribeEvent public void onGainItem(GainItemEvent event) { - System.out.println("Gained an item: " + event.stack.getUnlocalizedName()); checkForMatch(event.stack); } @SubscribeEvent public void onPickupItem(EntityItemPickupEvent event) { - if (event.getItem() != null && event.getItem().getEntityItem() != null) { - ItemStack stack = event.getItem().getEntityItem(); - checkForMatch(stack); - } + if (event.getItem() != null) + checkForMatch(event.getItem().getEntityItem()); } @SubscribeEvent - public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { - if (callCraft) - checkForMatch(event.crafting); + public void onLoseItem(LoseItemEvent event) { + if (event.stack != null) + removeCollectedItemCount(event.stack); + } - callCraft = !callCraft; + @SubscribeEvent + public void onDropItem(ItemTossEvent event) { + removeCollectedItemCount(event.getEntityItem().getEntityItem()); + } + + @SubscribeEvent + public void onDestroyItem(PlayerDestroyItemEvent event) { + removeCollectedItemCount(event.getOriginal()); } @SubscribeEvent - public void onItemToss(ItemTossEvent event) { - if (event.getEntityItem() != null && event.getEntityItem().getEntityItem() != null) { - ItemStack stack = event.getEntityItem().getEntityItem(); - removeCollectedItem(stack); + public void onBlockPlace(PlaceEvent event) { + if (!event.isCanceled() && event.getPlacedBlock() != null) { + ItemStack stack = new ItemStack(event.getPlacedBlock().getBlock()); + removeCollectedItemCount(stack); } } + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ private boolean getVariant(ItemStack is) { - for (ItemMatcher matcher : matchers) { + for (ItemQuitMatcher matcher : matchers) { if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) return true; @@ -116,53 +136,46 @@ private boolean getVariant(ItemStack is) { return false; } - private int getCraftedItemCount(ItemStack is) { + private void addCollectedItemCount(ItemStack is) { boolean variant = getVariant(is); + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); if (variant) - return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 - : collectedItems.get(is.getUnlocalizedName()); + collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); else - return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 - : collectedItems.get(is.getItem().getUnlocalizedName()); + collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); } - private void addCollectedItem(ItemStack is) { + private void removeCollectedItemCount(ItemStack is) { boolean variant = getVariant(is); - if (variant) { - int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getUnlocalizedName())); - collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - } else { - int prev = (collectedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getItem().getUnlocalizedName())); - collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - } + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + if (variant) + collectedItems.put(is.getUnlocalizedName(), prev - is.getCount()); + else + collectedItems.put(is.getItem().getUnlocalizedName(), prev - is.getCount()); } - private void removeCollectedItem(ItemStack is) { + private int getCollectedItemCount(ItemStack is) { boolean variant = getVariant(is); - if (variant) { - int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getUnlocalizedName())); - collectedItems.put(is.getUnlocalizedName(), Integer.max(0, prev - is.getCount())); - } else { - int prev = (collectedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getItem().getUnlocalizedName())); - collectedItems.put(is.getItem().getUnlocalizedName(), Integer.max(0, prev - is.getCount())); - } + if (variant) + return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 : collectedItems.get(is.getUnlocalizedName()); + else + return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName()); } private void checkForMatch(ItemStack is) { - int savedCrafted = getCraftedItemCount(is); - if (is != null && is.getItem() != null) { + int savedCollected = getCollectedItemCount(is); + if (is != null) { for (ItemQuitMatcher matcher : this.matchers) { if (matcher.matches(is)) { - if (savedCrafted != 0) { - if (is.getCount() + savedCrafted >= matcher.matchSpec.getAmount()) { + if (savedCollected != 0) { + if (is.getCount() + savedCollected >= matcher.matchSpec.getAmount()) { this.quitCode = matcher.description(); this.wantToQuit = true; } @@ -173,7 +186,7 @@ private void checkForMatch(ItemStack is) { } } - addCollectedItem(is); + addCollectedItemCount(is); } } -} +} \ No newline at end of file diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java index 9ebc9caf6..1ab383b99 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java @@ -16,131 +16,137 @@ import com.microsoft.Malmo.Schemas.MissionInit; /** - * * @author Cayden Codel, Carnegie Mellon University - * - * Gives agents rewards when items are smelted. - * + *

+ * Gives agents rewards when items are smelted. Handles variants and colors. */ public class AgentQuitFromSmeltingItemImplementation extends HandlerBase implements IWantToQuit { - private AgentQuitFromSmeltingItem params; - private HashMap smeltedItems; - private List matchers; - private String quitCode = ""; - boolean wantToQuit = false; - boolean callSmelt = true; - - public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { - String description; - - ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { - super(spec); - this.description = spec.getDescription(); - } - - String description() { - return this.description; - } - } - - @Override - public boolean parseParameters(Object params) { - if (params == null || !(params instanceof AgentQuitFromSmeltingItem)) - return false; - - this.params = (AgentQuitFromSmeltingItem) params; - this.matchers = new ArrayList(); - for (BlockOrItemSpecWithDescription bs : this.params.getItem()) - this.matchers.add(new ItemQuitMatcher(bs)); - return true; - } - - @Override - public boolean doIWantToQuit(MissionInit missionInit) { - return this.wantToQuit; - } - - @Override - public String getOutcome() { - return this.quitCode; - } - - @Override - public void prepare(MissionInit missionInit) { - MinecraftForge.EVENT_BUS.register(this); - smeltedItems = new HashMap(); - } - - @Override - public void cleanup() { - MinecraftForge.EVENT_BUS.unregister(this); - } - - @SubscribeEvent - public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { - if (callSmelt) - checkForMatch(event.smelting); - - callSmelt = !callSmelt; - } - - private boolean getVariant(ItemStack is) { - for (ItemMatcher matcher : matchers) { - if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { - if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) - return true; - if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) - return true; - } - } - - return false; - } - - private int getSmeltedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) - return (smeltedItems.get(is.getUnlocalizedName()) == null) ? 0 : smeltedItems.get(is.getUnlocalizedName()); - else - return (smeltedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 - : smeltedItems.get(is.getItem().getUnlocalizedName()); - - } - - private void addSmeltedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) { - int prev = (smeltedItems.get(is.getUnlocalizedName()) == null ? 0 - : smeltedItems.get(is.getUnlocalizedName())); - smeltedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - } else { - int prev = (smeltedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 - : smeltedItems.get(is.getItem().getUnlocalizedName())); - smeltedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - } - } - - private void checkForMatch(ItemStack is) { - int savedSmelted = getSmeltedItemCount(is); - if (is != null && is.getItem() != null) { - for (ItemQuitMatcher matcher : this.matchers) { - if (matcher.matches(is)) { - if (savedSmelted != 0) { - if (is.getCount() + savedSmelted >= matcher.matchSpec.getAmount()) { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } else if (is.getCount() >= matcher.matchSpec.getAmount()) { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } - } - - addSmeltedItemCount(is); - } - } + private AgentQuitFromSmeltingItem params; + private HashMap smeltedItems; + private List matchers; + private String quitCode = ""; + private boolean wantToQuit = false; + private boolean callSmelt = true; + + public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { + String description; + + ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { + super(spec); + this.description = spec.getDescription(); + } + + String description() { + return this.description; + } + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof AgentQuitFromSmeltingItem)) + return false; + + this.params = (AgentQuitFromSmeltingItem) params; + this.matchers = new ArrayList(); + for (BlockOrItemSpecWithDescription bs : this.params.getItem()) + this.matchers.add(new ItemQuitMatcher(bs)); + return true; + } + + @Override + public boolean doIWantToQuit(MissionInit missionInit) { + return this.wantToQuit; + } + + @Override + public String getOutcome() { + return this.quitCode; + } + + @Override + public void prepare(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.register(this); + smeltedItems = new HashMap(); + } + + @Override + public void cleanup() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { + if (callSmelt) + checkForMatch(event.smelting); + + callSmelt = !callSmelt; + } + + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getSmeltedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (smeltedItems.get(is.getUnlocalizedName()) == null) ? 0 : smeltedItems.get(is.getUnlocalizedName()); + else + return (smeltedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : smeltedItems.get(is.getItem().getUnlocalizedName()); + + } + + private void addSmeltedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (smeltedItems.get(is.getUnlocalizedName()) == null ? 0 + : smeltedItems.get(is.getUnlocalizedName())); + smeltedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + } else { + int prev = (smeltedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : smeltedItems.get(is.getItem().getUnlocalizedName())); + smeltedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + } + + private void checkForMatch(ItemStack is) { + int savedSmelted = getSmeltedItemCount(is); + if (is != null) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedSmelted != 0) { + if (is.getCount() + savedSmelted >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } + } + + addSmeltedItemCount(is); + } + } } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCollectingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCollectingItemImplementation.java index 6907e56d2..ef775b916 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCollectingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCollectingItemImplementation.java @@ -1,31 +1,19 @@ -// -------------------------------------------------------------------------------------------------- -// Copyright (c) 2016 Microsoft Corporation -// -// 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 com.microsoft.Malmo.MissionHandlers; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; - +import java.util.ArrayList; +import java.util.HashMap; import java.util.Map; -import javax.xml.bind.DatatypeConverter; +import com.microsoft.Malmo.MalmoMod; +import com.microsoft.Malmo.MalmoMod.IMalmoMessageListener; +import com.microsoft.Malmo.MalmoMod.MalmoMessageType; +import com.microsoft.Malmo.MissionHandlerInterfaces.IRewardProducer; +import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithReward; +import com.microsoft.Malmo.Schemas.MissionInit; +import com.microsoft.Malmo.Schemas.RewardForCollectingItem; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; import net.minecraftforge.common.MinecraftForge; @@ -34,95 +22,171 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.network.ByteBufUtils; -import com.microsoft.Malmo.MalmoMod; -import com.microsoft.Malmo.MalmoMod.IMalmoMessageListener; -import com.microsoft.Malmo.MalmoMod.MalmoMessageType; -import com.microsoft.Malmo.MissionHandlerInterfaces.IRewardProducer; -import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithReward; -import com.microsoft.Malmo.Schemas.MissionInit; -import com.microsoft.Malmo.Schemas.RewardForCollectingItem; +import javax.xml.bind.DatatypeConverter; + +/** + * @author Cayden Codel, Carnegie Mellon University + *

+ * Sends a reward when the agent collected the specified item with + * specified amounts. Counter is absolute. + */ +public class RewardForCollectingItemImplementation extends RewardForItemBase + implements IRewardProducer, IMalmoMessageListener { -public class RewardForCollectingItemImplementation extends RewardForItemBase implements IRewardProducer, IMalmoMessageListener -{ private RewardForCollectingItem params; + private ArrayList matchers; + private HashMap craftedItems; - @Override - public void onMessage(MalmoMessageType messageType, Map data) - { - String bufstring = data.get("message"); - ByteBuf buf = Unpooled.copiedBuffer(DatatypeConverter.parseBase64Binary(bufstring)); - ItemStack itemStack = ByteBufUtils.readItemStack(buf); - if (itemStack != null && itemStack.getItem() != null) - { - accumulateReward(this.params.getDimension(), itemStack); + @SubscribeEvent + public void onPickupItem(EntityItemPickupEvent event) { + if (event.getItem() != null) { + checkForMatch(event.getItem().getEntityItem()); + if (event.getEntityPlayer() instanceof EntityPlayerMP) + sendItemStackToClient((EntityPlayerMP) event.getEntityPlayer(), MalmoMessageType.SERVER_COLLECTITEM, event.getItem().getEntityItem()); } - else - { - System.out.println("Error - couldn't understand the itemstack we received."); + } + + @SubscribeEvent + public void onGainItem(GainItemEvent event) { + if (event.stack != null) { + accumulateReward(this.params.getDimension(), event.stack); } } - - public static class GainItemEvent extends Event - { - public final ItemStack stack; - public GainItemEvent(ItemStack stack) - { - this.stack = stack; + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } } + + return false; } - @Override - public boolean parseParameters(Object params) { - if (params == null || !(params instanceof RewardForCollectingItem)) - return false; + private int getCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); - // Build up a map of rewards per item: - this.params = (RewardForCollectingItem) params; - for (BlockOrItemSpecWithReward is : this.params.getItem()) - addItemSpecToRewardStructure(is); + if (variant) + return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); + else + return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName()); + } - return true; + private void addCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getUnlocalizedName())); + if (variant) + craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + else + craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); } - @SubscribeEvent - public void onGainItem(GainItemEvent event) - { - if (event.stack != null) - { - accumulateReward(this.params.getDimension(), event.stack); + private void checkForMatch(ItemStack is) { + int savedCollected = getCollectedItemCount(is); + if (is != null) { + for (ItemMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (!params.isSparse()) { + if (savedCollected != 0 && savedCollected < matcher.matchSpec.getAmount()) { + for (int i = savedCollected; i < matcher.matchSpec.getAmount() + && i - savedCollected < is.getCount(); i++) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + + } else if (savedCollected != 0 && savedCollected >= matcher.matchSpec.getAmount()) { + // Do nothing + } else { + for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } else { + if (savedCollected < matcher.matchSpec.getAmount() + && savedCollected + is.getCount() >= matcher.matchSpec.getAmount()) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } + } + + addCollectedItemCount(is); } } - @SubscribeEvent - public void onPickupItem(EntityItemPickupEvent event) - { - if (event.getItem() != null && event.getEntityPlayer() instanceof EntityPlayerMP ) - { - // This event is received on the server side, so we need to pass it to the client. - sendItemStackToClient((EntityPlayerMP)event.getEntityPlayer(), MalmoMessageType.SERVER_COLLECTITEM, event.getItem().getEntityItem()); - } + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof RewardForCollectingItem)) + return false; + + matchers = new ArrayList(); + + this.params = (RewardForCollectingItem) params; + for (BlockOrItemSpecWithReward spec : this.params.getItem()) + this.matchers.add(new ItemMatcher(spec)); + + return true; } @Override - public void prepare(MissionInit missionInit) - { + public void prepare(MissionInit missionInit) { super.prepare(missionInit); MinecraftForge.EVENT_BUS.register(this); MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + craftedItems = new HashMap(); } @Override - public void getReward(MissionInit missionInit, MultidimensionalReward reward) - { + public void getReward(MissionInit missionInit, MultidimensionalReward reward) { super.getReward(missionInit, reward); } @Override - public void cleanup() - { + public void cleanup() { super.cleanup(); MinecraftForge.EVENT_BUS.unregister(this); MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); } -} + + @Override + public void onMessage(MalmoMessageType messageType, Map data) { + String buffString = data.get("message"); + ByteBuf buf = Unpooled.copiedBuffer(DatatypeConverter.parseBase64Binary(buffString)); + ItemStack itemStack = ByteBufUtils.readItemStack(buf); + if (itemStack != null) { + accumulateReward(this.params.getDimension(), itemStack); + } else { + System.out.println("Error - couldn't understand the itemstack we received."); + } + } + + public static class GainItemEvent extends Event { + public final ItemStack stack; + + public GainItemEvent(ItemStack stack) { + this.stack = stack; + } + } +} \ No newline at end of file diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java index 8329fddd6..0b6ed8030 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java @@ -18,154 +18,145 @@ import net.minecraftforge.fml.common.gameevent.PlayerEvent; /** - * * @author Cayden Codel, Carnegie Mellon University - * - * Sends a reward when the agent crafts the specified item with - * specified amounts. + *

+ * Sends a reward when the agent crafts the specified item with + * specified amounts. */ public class RewardForCraftingItemImplementation extends RewardForItemBase - implements IRewardProducer, IMalmoMessageListener { - - private RewardForCraftingItem params; - private ArrayList matchers; - private HashMap craftedItems; - boolean callCraft = true; - - @SubscribeEvent - public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { - if (callCraft) - checkForMatch(event.crafting); - - callCraft = !callCraft; - } - - private boolean getVariant(ItemStack is) { - for (ItemMatcher matcher : matchers) { - if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { - if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) - return true; - if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) - return true; - } - } - - return false; - } - - private int getCraftedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) - return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); - else - return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 - : craftedItems.get(is.getItem().getUnlocalizedName()); - - } - - private void addCraftedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) { - int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 - : craftedItems.get(is.getUnlocalizedName())); - craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - } else { - int prev = (craftedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 - : craftedItems.get(is.getItem().getUnlocalizedName())); - craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - } - } - - private void checkForMatch(ItemStack is) { - //System.out.println("Checking for match on " + is.getItem().getUnlocalizedName()); - int savedCrafted = getCraftedItemCount(is); - //System.out.println("Previous saved amount is " + savedCrafted); - if (is != null && is.getItem() != null) { - for (ItemMatcher matcher : this.matchers) { - if (matcher.matches(is)) { - if (!params.isSparse()) { - if (savedCrafted != 0 && savedCrafted < matcher.matchSpec.getAmount()) { - for (int i = savedCrafted; i < matcher.matchSpec.getAmount() - && i - savedCrafted < is.getCount(); i++) { - //System.out.println("Sparse, had nonzero saved crafted amount, giving a reward of " - // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); - this.adjustAndDistributeReward( - ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), - params.getDimension(), - ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); - } - - } else if (savedCrafted != 0 && savedCrafted >= matcher.matchSpec.getAmount()) { - // Do nothing - //System.out - // .println("Sparse, had nonzero saved crafted amount, but not enough new for reward"); - } else { - for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { - //System.out.println("Had zero saved crafted amount, giving a reward of " - // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); - this.adjustAndDistributeReward( - ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), - params.getDimension(), - ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); - } - - } - } else { - if (savedCrafted < matcher.matchSpec.getAmount() - && savedCrafted + is.getCount() >= matcher.matchSpec.getAmount()) { - //System.out.println("Not sparse, giving a reward of " - // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); - this.adjustAndDistributeReward( - ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), - params.getDimension(), - ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); - } - } - } - } - - addCraftedItemCount(is); - } - - } - - @Override - public boolean parseParameters(Object params) { - if (params == null || !(params instanceof RewardForCraftingItem)) - return false; - - matchers = new ArrayList(); - - this.params = (RewardForCraftingItem) params; - for (BlockOrItemSpecWithReward spec : this.params.getItem()) - this.matchers.add(new ItemMatcher(spec)); - - return true; - } - - @Override - public void prepare(MissionInit missionInit) { - super.prepare(missionInit); - MinecraftForge.EVENT_BUS.register(this); - MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); - craftedItems = new HashMap(); - } - - @Override - public void getReward(MissionInit missionInit, MultidimensionalReward reward) { - super.getReward(missionInit, reward); - } - - @Override - public void cleanup() { - super.cleanup(); - MinecraftForge.EVENT_BUS.unregister(this); - MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); - } - - @Override - public void onMessage(MalmoMessageType messageType, Map data) { - } -} + implements IRewardProducer, IMalmoMessageListener { + + private RewardForCraftingItem params; + private ArrayList matchers; + private HashMap craftedItems; + private boolean callCraft = true; + + @SubscribeEvent + public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { + if (callCraft) + checkForMatch(event.crafting); + + callCraft = !callCraft; + } + + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); + else + return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName()); + } + + private void addCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getUnlocalizedName())); + if (variant) + craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + else + craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + + private void checkForMatch(ItemStack is) { + int savedCrafted = getCraftedItemCount(is); + if (is != null) { + for (ItemMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (!params.isSparse()) { + if (savedCrafted != 0 && savedCrafted < matcher.matchSpec.getAmount()) { + for (int i = savedCrafted; i < matcher.matchSpec.getAmount() + && i - savedCrafted < is.getCount(); i++) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + + } else if (savedCrafted != 0 && savedCrafted >= matcher.matchSpec.getAmount()) { + // Do nothing + } else { + for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } else { + if (savedCrafted < matcher.matchSpec.getAmount() + && savedCrafted + is.getCount() >= matcher.matchSpec.getAmount()) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } + } + + addCraftedItemCount(is); + } + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof RewardForCraftingItem)) + return false; + + matchers = new ArrayList(); + + this.params = (RewardForCraftingItem) params; + for (BlockOrItemSpecWithReward spec : this.params.getItem()) + this.matchers.add(new ItemMatcher(spec)); + + return true; + } + + @Override + public void prepare(MissionInit missionInit) { + super.prepare(missionInit); + MinecraftForge.EVENT_BUS.register(this); + MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + craftedItems = new HashMap(); + } + + @Override + public void getReward(MissionInit missionInit, MultidimensionalReward reward) { + super.getReward(missionInit, reward); + } + + @Override + public void cleanup() { + super.cleanup(); + MinecraftForge.EVENT_BUS.unregister(this); + MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + } + + @Override + public void onMessage(MalmoMessageType messageType, Map data) { + } +} \ No newline at end of file diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForPossessingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForPossessingItemImplementation.java new file mode 100644 index 000000000..33473a80b --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForPossessingItemImplementation.java @@ -0,0 +1,232 @@ +package com.microsoft.Malmo.MissionHandlers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import com.microsoft.Malmo.MalmoMod; +import com.microsoft.Malmo.MalmoMod.IMalmoMessageListener; +import com.microsoft.Malmo.MalmoMod.MalmoMessageType; +import com.microsoft.Malmo.MissionHandlerInterfaces.IRewardProducer; +import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithReward; +import com.microsoft.Malmo.Schemas.MissionInit; +import com.microsoft.Malmo.MissionHandlers.RewardForDiscardingItemImplementation.LoseItemEvent; +import com.microsoft.Malmo.Schemas.RewardForPossessingItem; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.item.ItemTossEvent; +import net.minecraftforge.event.entity.player.EntityItemPickupEvent; +import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent; +import net.minecraftforge.event.world.BlockEvent.PlaceEvent; +import net.minecraftforge.fml.common.eventhandler.Event; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.ByteBufUtils; + +import javax.xml.bind.DatatypeConverter; + +/** + * @author Cayden Codel, Carnegie Mellon University + *

+ * Sends a reward when the agent possesses the specified item with + * specified amounts. The counter is relative, meaning it goes down if items are placed, lost, or destroyed. + */ +public class RewardForPossessingItemImplementation extends RewardForItemBase + implements IRewardProducer, IMalmoMessageListener { + + private RewardForPossessingItem params; + private ArrayList matchers; + private HashMap collectedItems; + + @SubscribeEvent + public void onPickupItem(EntityItemPickupEvent event) { + if (event.getItem() != null) { + checkForMatch(event.getItem().getEntityItem()); + if (event.getEntityPlayer() instanceof EntityPlayerMP) + sendItemStackToClient((EntityPlayerMP) event.getEntityPlayer(), MalmoMessageType.SERVER_COLLECTITEM, event.getItem().getEntityItem()); + } + } + + @SubscribeEvent + public void onGainItem(GainItemEvent event) { + if (event.stack != null) { + accumulateReward(this.params.getDimension(), event.stack); + } + } + + @SubscribeEvent + public void onLoseItem(LoseItemEvent event) { + if (event.stack != null) + removeCollectedItemCount(event.stack); + } + + @SubscribeEvent + public void onDropItem(ItemTossEvent event) { + removeCollectedItemCount(event.getEntityItem().getEntityItem()); + } + + @SubscribeEvent + public void onDestroyItem(PlayerDestroyItemEvent event) { + removeCollectedItemCount(event.getOriginal()); + } + + @SubscribeEvent + public void onBlockPlace(PlaceEvent event) { + if (!event.isCanceled() && event.getPlacedBlock() != null) { + ItemStack stack = new ItemStack(event.getPlacedBlock().getBlock()); + removeCollectedItemCount(stack); + } + } + + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 : collectedItems.get(is.getUnlocalizedName()); + else + return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName()); + } + + private void addCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + if (variant) + collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + else + collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + + private void removeCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + if (variant) + collectedItems.put(is.getUnlocalizedName(), prev - is.getCount()); + else + collectedItems.put(is.getItem().getUnlocalizedName(), prev - is.getCount()); + } + + private void checkForMatch(ItemStack is) { + int savedCollected = getCollectedItemCount(is); + if (is != null) { + for (ItemMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (!params.isSparse()) { + if (savedCollected != 0 && savedCollected < matcher.matchSpec.getAmount()) { + for (int i = savedCollected; i < matcher.matchSpec.getAmount() + && i - savedCollected < is.getCount(); i++) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + + } else if (savedCollected != 0 && savedCollected >= matcher.matchSpec.getAmount()) { + // Do nothing + } else { + for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } else { + if (savedCollected < matcher.matchSpec.getAmount() + && savedCollected + is.getCount() >= matcher.matchSpec.getAmount()) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } + } + + addCollectedItemCount(is); + } + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof RewardForPossessingItem)) + return false; + + matchers = new ArrayList(); + + this.params = (RewardForPossessingItem) params; + for (BlockOrItemSpecWithReward spec : this.params.getItem()) + this.matchers.add(new ItemMatcher(spec)); + + return true; + } + + @Override + public void prepare(MissionInit missionInit) { + super.prepare(missionInit); + MinecraftForge.EVENT_BUS.register(this); + MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + collectedItems = new HashMap(); + } + + @Override + public void getReward(MissionInit missionInit, MultidimensionalReward reward) { + super.getReward(missionInit, reward); + } + + @Override + public void cleanup() { + super.cleanup(); + MinecraftForge.EVENT_BUS.unregister(this); + MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + } + + @Override + public void onMessage(MalmoMessageType messageType, Map data) { + String buffString = data.get("message"); + ByteBuf buf = Unpooled.copiedBuffer(DatatypeConverter.parseBase64Binary(buffString)); + ItemStack itemStack = ByteBufUtils.readItemStack(buf); + if (itemStack != null) { + accumulateReward(this.params.getDimension(), itemStack); + } else { + System.out.println("Error - couldn't understand the itemstack we received."); + } + } + + public static class GainItemEvent extends Event { + public final ItemStack stack; + + public GainItemEvent(ItemStack stack) { + this.stack = stack; + } + } +} \ No newline at end of file diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java index ee4a5fded..3b6bae305 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java @@ -10,27 +10,26 @@ import com.microsoft.Malmo.MissionHandlerInterfaces.IRewardProducer; import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithReward; import com.microsoft.Malmo.Schemas.MissionInit; -import com.microsoft.Malmo.Schemas.RewardForSmeltingItem; +import com.microsoft.Malmo.Schemas.RewardForSmeltingItem; import net.minecraft.item.ItemStack; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent; /** - * * @author Cayden Codel, Carnegie Mellon University - * - * Sends a reward when the agent smelts the specified item with - * specified amounts. + *

+ * Sends a reward when the agent smelts the specified item with + * specified amounts. */ public class RewardForSmeltingItemImplementation extends RewardForItemBase implements IRewardProducer, IMalmoMessageListener { private RewardForSmeltingItem params; private ArrayList matchers; - private HashMap smeltedItems; - boolean callSmelt = true; + private HashMap craftedItems; + private boolean callSmelt = true; @SubscribeEvent public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { @@ -40,6 +39,14 @@ public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { callSmelt = !callSmelt; } + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ private boolean getVariant(ItemStack is) { for (ItemMatcher matcher : matchers) { if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { @@ -53,70 +60,55 @@ private boolean getVariant(ItemStack is) { return false; } - private int getCraftedItemCount(ItemStack is) { + private int getSmeltedItemCount(ItemStack is) { boolean variant = getVariant(is); if (variant) - return (smeltedItems.get(is.getUnlocalizedName()) == null) ? 0 : smeltedItems.get(is.getUnlocalizedName()); + return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); else - return (smeltedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 - : smeltedItems.get(is.getItem().getUnlocalizedName()); - + return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName()); } private void addSmeltedItemCount(ItemStack is) { boolean variant = getVariant(is); - if (variant) { - int prev = (smeltedItems.get(is.getUnlocalizedName()) == null ? 0 - : smeltedItems.get(is.getUnlocalizedName())); - smeltedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - } else { - int prev = (smeltedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 - : smeltedItems.get(is.getItem().getUnlocalizedName())); - smeltedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - } + int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getUnlocalizedName())); + if (variant) + craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + else + craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); } private void checkForMatch(ItemStack is) { - //System.out.println("Checking for match on " + is.getItem().getUnlocalizedName()); - int savedCrafted = getCraftedItemCount(is); - //System.out.println("Previous saved amount is " + savedCrafted); - if (is != null && is.getItem() != null) { + int savedSmelted = getSmeltedItemCount(is); + if (is != null) { for (ItemMatcher matcher : this.matchers) { if (matcher.matches(is)) { if (!params.isSparse()) { - if (savedCrafted != 0 && savedCrafted < matcher.matchSpec.getAmount()) { - for (int i = savedCrafted; i < matcher.matchSpec.getAmount() - && i - savedCrafted < is.getCount(); i++) { - //System.out.println("Sparse, had nonzero saved crafted amount, giving a reward of " - // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); + if (savedSmelted != 0 && savedSmelted < matcher.matchSpec.getAmount()) { + for (int i = savedSmelted; i < matcher.matchSpec.getAmount() + && i - savedSmelted < is.getCount(); i++) { this.adjustAndDistributeReward( ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), params.getDimension(), ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); } - } else if (savedCrafted != 0 && savedCrafted >= matcher.matchSpec.getAmount()) { + } else if (savedSmelted != 0 && savedSmelted >= matcher.matchSpec.getAmount()) { // Do nothing - //System.out - // .println("Sparse, had nonzero saved crafted amount, but not enough new for reward"); } else { for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { - //System.out.println("Had zero saved crafted amount, giving a reward of " - // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); this.adjustAndDistributeReward( ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), params.getDimension(), ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); } - } } else { - if (savedCrafted < matcher.matchSpec.getAmount() - && savedCrafted + is.getCount() >= matcher.matchSpec.getAmount()) { - //System.out.println("Not sparse, giving a reward of " - // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); + if (savedSmelted < matcher.matchSpec.getAmount() + && savedSmelted + is.getCount() >= matcher.matchSpec.getAmount()) { this.adjustAndDistributeReward( ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), params.getDimension(), @@ -128,12 +120,11 @@ private void checkForMatch(ItemStack is) { addSmeltedItemCount(is); } - } @Override public boolean parseParameters(Object params) { - if (params == null || !(params instanceof RewardForSmeltingItem)) + if (!(params instanceof RewardForSmeltingItem)) return false; matchers = new ArrayList(); @@ -150,7 +141,7 @@ public void prepare(MissionInit missionInit) { super.prepare(missionInit); MinecraftForge.EVENT_BUS.register(this); MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); - smeltedItems = new HashMap(); + craftedItems = new HashMap(); } @Override @@ -168,4 +159,4 @@ public void cleanup() { @Override public void onMessage(MalmoMessageType messageType, Map data) { } -} +} \ No newline at end of file diff --git a/Schemas/Mission.xsd b/Schemas/Mission.xsd index fdfd15e5d..b49ce2bf7 100644 --- a/Schemas/Mission.xsd +++ b/Schemas/Mission.xsd @@ -358,6 +358,7 @@ + @@ -378,9 +379,9 @@ + - diff --git a/Schemas/Mission.xsd.in b/Schemas/Mission.xsd.in index b9cb213b8..847715f18 100644 --- a/Schemas/Mission.xsd.in +++ b/Schemas/Mission.xsd.in @@ -358,6 +358,7 @@ + @@ -378,9 +379,9 @@ + - diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd index 509ee37fb..318b386a0 100644 --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -2206,12 +2206,36 @@ Sends a reward when the agent collects a specific item. + + If Sparse is set to true, will only give full reward on collecting entire amount. + + Otherwise, will give the reward amount notated for each item collected up to the amount noted. + + + + + + + + + Sends a reward when the agent collects a specific item. + + If Sparse is set to true, will only give full reward on possessing the entire amount. + + Otherwise, will give the rewards amount notated for each item crafted up to the amount noted. + + + + + + + @@ -2230,7 +2254,7 @@ - + @@ -2249,7 +2273,7 @@ - + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index b777dcd20..965325d69 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -2206,12 +2206,36 @@ Sends a reward when the agent collects a specific item. + + If Sparse is set to true, will only give full reward on collecting entire amount. + + Otherwise, will give the reward amount notated for each item collected up to the amount noted. + + + + + + + + + Sends a reward when the agent collects a specific item. + + If Sparse is set to true, will only give full reward on possessing the entire amount. + + Otherwise, will give the rewards amount notated for each item crafted up to the amount noted. + + + + + + + @@ -2230,7 +2254,7 @@ - + @@ -2249,7 +2273,7 @@ - + From c5328899701c047c22aa02fdc7152dbcadd848f2 Mon Sep 17 00:00:00 2001 From: ccodel Date: Fri, 8 Feb 2019 23:09:58 -0500 Subject: [PATCH 05/40] Updated smelting to call matcher once every four now --- ...entQuitFromSmeltingItemImplementation.java | 26 +- .../RewardForSmeltingItemImplementation.java | 270 +++++++++--------- 2 files changed, 147 insertions(+), 149 deletions(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java index 1ab383b99..269317a92 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java @@ -27,7 +27,7 @@ public class AgentQuitFromSmeltingItemImplementation extends HandlerBase impleme private List matchers; private String quitCode = ""; private boolean wantToQuit = false; - private boolean callSmelt = true; + private int callSmelt = 0; public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { String description; @@ -77,10 +77,10 @@ public void cleanup() { @SubscribeEvent public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { - if (callSmelt) + if (callSmelt % 4 == 0) checkForMatch(event.smelting); - callSmelt = !callSmelt; + callSmelt = (callSmelt + 1) % 4; } /** @@ -131,22 +131,20 @@ private void addSmeltedItemCount(ItemStack is) { private void checkForMatch(ItemStack is) { int savedSmelted = getSmeltedItemCount(is); - if (is != null) { - for (ItemQuitMatcher matcher : this.matchers) { - if (matcher.matches(is)) { - if (savedSmelted != 0) { - if (is.getCount() + savedSmelted >= matcher.matchSpec.getAmount()) { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedSmelted != 0) { + if (is.getCount() + savedSmelted >= matcher.matchSpec.getAmount()) { this.quitCode = matcher.description(); this.wantToQuit = true; } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; } } - - addSmeltedItemCount(is); } + + addSmeltedItemCount(is); } } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java index 3b6bae305..9eee04e9b 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java @@ -24,139 +24,139 @@ * specified amounts. */ public class RewardForSmeltingItemImplementation extends RewardForItemBase - implements IRewardProducer, IMalmoMessageListener { - - private RewardForSmeltingItem params; - private ArrayList matchers; - private HashMap craftedItems; - private boolean callSmelt = true; - - @SubscribeEvent - public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { - if (callSmelt) - checkForMatch(event.smelting); - - callSmelt = !callSmelt; - } - - /** - * Checks whether the ItemStack matches a variant stored in the item list. If - * so, returns true, else returns false. - * - * @param is The item stack - * @return If the stack is allowed in the item matchers and has color or - * variants enabled, returns true, else false. - */ - private boolean getVariant(ItemStack is) { - for (ItemMatcher matcher : matchers) { - if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { - if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) - return true; - if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) - return true; - } - } - - return false; - } - - private int getSmeltedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) - return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); - else - return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 - : craftedItems.get(is.getItem().getUnlocalizedName()); - } - - private void addSmeltedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 - : craftedItems.get(is.getUnlocalizedName())); - if (variant) - craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - else - craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - } - - private void checkForMatch(ItemStack is) { - int savedSmelted = getSmeltedItemCount(is); - if (is != null) { - for (ItemMatcher matcher : this.matchers) { - if (matcher.matches(is)) { - if (!params.isSparse()) { - if (savedSmelted != 0 && savedSmelted < matcher.matchSpec.getAmount()) { - for (int i = savedSmelted; i < matcher.matchSpec.getAmount() - && i - savedSmelted < is.getCount(); i++) { - this.adjustAndDistributeReward( - ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), - params.getDimension(), - ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); - } - - } else if (savedSmelted != 0 && savedSmelted >= matcher.matchSpec.getAmount()) { - // Do nothing - } else { - for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { - this.adjustAndDistributeReward( - ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), - params.getDimension(), - ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); - } - } - } else { - if (savedSmelted < matcher.matchSpec.getAmount() - && savedSmelted + is.getCount() >= matcher.matchSpec.getAmount()) { - this.adjustAndDistributeReward( - ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), - params.getDimension(), - ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); - } - } - } - } - - addSmeltedItemCount(is); - } - } - - @Override - public boolean parseParameters(Object params) { - if (!(params instanceof RewardForSmeltingItem)) - return false; - - matchers = new ArrayList(); - - this.params = (RewardForSmeltingItem) params; - for (BlockOrItemSpecWithReward spec : this.params.getItem()) - this.matchers.add(new ItemMatcher(spec)); - - return true; - } - - @Override - public void prepare(MissionInit missionInit) { - super.prepare(missionInit); - MinecraftForge.EVENT_BUS.register(this); - MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); - craftedItems = new HashMap(); - } - - @Override - public void getReward(MissionInit missionInit, MultidimensionalReward reward) { - super.getReward(missionInit, reward); - } - - @Override - public void cleanup() { - super.cleanup(); - MinecraftForge.EVENT_BUS.unregister(this); - MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); - } - - @Override - public void onMessage(MalmoMessageType messageType, Map data) { - } + implements IRewardProducer, IMalmoMessageListener { + + private RewardForSmeltingItem params; + private ArrayList matchers; + private HashMap craftedItems; + private int callSmelt = 0; + + @SubscribeEvent + public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { + if (callSmelt % 4 == 0) + checkForMatch(event.smelting); + + callSmelt = (callSmelt + 1) % 4; + } + + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getSmeltedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); + else + return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName()); + } + + private void addSmeltedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getUnlocalizedName())); + if (variant) + craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + else + craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + + private void checkForMatch(ItemStack is) { + int savedSmelted = getSmeltedItemCount(is); + for (ItemMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (!params.isSparse()) { + if (savedSmelted != 0 && savedSmelted < matcher.matchSpec.getAmount()) { + for (int i = savedSmelted; i < matcher.matchSpec.getAmount() + && i - savedSmelted < is.getCount(); i++) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + + } else if (savedSmelted != 0 && savedSmelted >= matcher.matchSpec.getAmount()) { + // Do nothing + } else { + for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { + System.out.println("Giving reward"); + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } else { + if (savedSmelted < matcher.matchSpec.getAmount() + && savedSmelted + is.getCount() >= matcher.matchSpec.getAmount()) { + System.out.println("Giving reward"); + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } + } + + addSmeltedItemCount(is); + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof RewardForSmeltingItem)) + return false; + + matchers = new ArrayList(); + + this.params = (RewardForSmeltingItem) params; + for (BlockOrItemSpecWithReward spec : this.params.getItem()) + this.matchers.add(new ItemMatcher(spec)); + + return true; + } + + @Override + public void prepare(MissionInit missionInit) { + super.prepare(missionInit); + MinecraftForge.EVENT_BUS.register(this); + MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + craftedItems = new HashMap(); + } + + @Override + public void getReward(MissionInit missionInit, MultidimensionalReward reward) { + super.getReward(missionInit, reward); + } + + @Override + public void cleanup() { + super.cleanup(); + MinecraftForge.EVENT_BUS.unregister(this); + MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + } + + @Override + public void onMessage(MalmoMessageType messageType, Map data) { + } } \ No newline at end of file From 8d84d9ba21cb69a48dd679773e935c7124be787c Mon Sep 17 00:00:00 2001 From: ccodel Date: Wed, 13 Feb 2019 17:05:07 -0500 Subject: [PATCH 06/40] Implemented nearby handlers, with lots of trig --- Malmo/src/MissionSpec.cpp | 16 +- .../NearbyCraftCommandsImplementation.java | 183 ++++++++++++++++++ .../NearbySmeltCommandsImplementation.java | 181 +++++++++++++++++ .../RewardForSmeltingItemImplementation.java | 4 +- Schemas/Mission.xsd | 2 + Schemas/Mission.xsd.in | 2 + Schemas/MissionHandlers.xsd | 54 ++++++ Schemas/MissionHandlers.xsd.in | 54 ++++++ 8 files changed, 494 insertions(+), 2 deletions(-) create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java diff --git a/Malmo/src/MissionSpec.cpp b/Malmo/src/MissionSpec.cpp index 9e7ce1575..ca56c3212 100755 --- a/Malmo/src/MissionSpec.cpp +++ b/Malmo/src/MissionSpec.cpp @@ -110,6 +110,7 @@ namespace malmo child.erase("FlatWorldGenerator"); child.erase("FileWorldGenerator"); child.erase("DefaultWorldGenerator"); + child.erase("BiomeGenerator"); } } @@ -137,6 +138,11 @@ namespace malmo if (defaultWorldGenerator) { defaultWorldGenerator.get().put(".forceReset", true); } + const auto& biomeWorldGenerator = + mission.get_child_optional("Mission.ServerSection.ServerHandlers.BiomeGenerator"); + if (biomeWorldGenerator) { + biomeWorldGenerator.get().put(".forceReset", true); + } } void MissionSpec::setTimeOfDay(int t,bool allowTimeToPass) @@ -361,7 +367,7 @@ namespace malmo void MissionSpec::observeCompass() { - mission.put("mission.AgentSection.AgentHandlers.ObservationFromCompass", ""); + mission.put("Mission.AgentSection.AgentHandlers.ObservationFromCompass", ""); } // ------------------ settings for the agents : command handlers -------------------------------- @@ -376,6 +382,8 @@ namespace malmo child.erase("DiscreteMovementCommands"); child.erase("AbsoluteMovementCommands"); child.erase("SimpleCraftCommands"); + child.erase("NearbyCraftCommands"); + child.erase("NearbySmeltCommands"); child.erase("ChatCommands"); child.erase("MissionQuitCommands"); } @@ -522,6 +530,12 @@ namespace malmo if (e.second.get_child_optional("AgentHandlers.SimpleCraftCommands")) command_handlers.push_back("SimpleCraft"); + + if (e.second.get_child_optional("AgentHandlers.NearbyCraftCommands")) + command_handlers.push_back("NearbyCraft"); + + if (e.second.get_child_optional("AgentHandlers.NearbySmeltCommands")) + command_handlers.push_back("NearbySmelt"); if (e.second.get_child_optional("AgentHandlers.MissionQuitCommands")) command_handlers.push_back("MissionQuit"); diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java new file mode 100644 index 000000000..b777b8d6b --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java @@ -0,0 +1,183 @@ +// -------------------------------------------------------------------------------------------------- +// Copyright (c) 2016 Microsoft Corporation +// +// 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 com.microsoft.Malmo.MissionHandlers; + +import io.netty.buffer.ByteBuf; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.block.BlockWorkbench; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.ByteBufUtils; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +import com.microsoft.Malmo.MalmoMod; +import com.microsoft.Malmo.Schemas.MissionInit; +import com.microsoft.Malmo.Schemas.SimpleCraftCommand; +import com.microsoft.Malmo.Schemas.NearbyCraftCommands; +import com.microsoft.Malmo.Utils.CraftingHelper; + +/** + * @author Cayden Codel, Carnegie Mellon University + *

+ * Extends the functionality of the SimpleCraftCommands by requiring a crafting table close-by. Only handles crafting, no smelting. + */ +public class NearbyCraftCommandsImplementation extends CommandBase { + private boolean isOverriding; + private static ArrayList craftingTables; + + public static class CraftMessage implements IMessage { + String parameters; + + public CraftMessage() { + } + + public CraftMessage(String parameters) { + this.parameters = parameters; + } + + @Override + public void fromBytes(ByteBuf buf) { + this.parameters = ByteBufUtils.readUTF8String(buf); + } + + @Override + public void toBytes(ByteBuf buf) { + ByteBufUtils.writeUTF8String(buf, this.parameters); + } + } + + @SubscribeEvent + public void onBlockPlace(BlockEvent.PlaceEvent event) { + if (!event.isCanceled() && event.getPlacedBlock().getBlock() instanceof BlockWorkbench) + craftingTables.add(event.getPos()); + } + + @SubscribeEvent + public void onBlockDestroy(BlockEvent.BreakEvent event) { + if (!event.isCanceled() && event.getState().getBlock() instanceof BlockWorkbench) + for (int i = craftingTables.size() - 1; i >= 0; i--) + if (craftingTables.get(i).equals(event.getPos())) + craftingTables.remove(i); + } + + public static class CraftMessageHandler implements IMessageHandler { + @Override + public IMessage onMessage(CraftMessage message, MessageContext ctx) { + EntityPlayerMP player = ctx.getServerHandler().playerEntity; + Vec3d headPos = new Vec3d(player.posX, player.posY + 1.6, player.posZ); + + // Location checking + boolean closeTable = false; + for (BlockPos furnace : craftingTables) { + Vec3d blockVec = new Vec3d(furnace.getX() + 0.5, furnace.getY() + 0.5, furnace.getZ() + 0.5); + + if (headPos.squareDistanceTo(blockVec) <= 25.0) { + // Within a reasonable FOV? + // Lots of trig, let's go + double fov = Minecraft.getMinecraft().gameSettings.fovSetting; + double height = Minecraft.getMinecraft().displayHeight; + double width = Minecraft.getMinecraft().displayWidth; + Vec3d lookVec = player.getLookVec(); + Vec3d toBlock = blockVec.subtract(headPos); + + // Projection of block onto player look vector - if greater than 0, then in front of us + double scalarProjection = lookVec.dotProduct(toBlock) / lookVec.lengthVector(); + if (scalarProjection > 0) { + Vec3d yUnit = new Vec3d(0, 1.0, 0); + Vec3d lookCross = lookVec.crossProduct(yUnit); + Vec3d blockProjectedOntoCross = lookCross.scale(lookCross.dotProduct(toBlock) / lookCross.lengthVector()); + Vec3d blockProjectedOntoPlayerPlane = toBlock.subtract(blockProjectedOntoCross); + double xyDot = lookVec.dotProduct(blockProjectedOntoPlayerPlane); + double pitchTheta = Math.acos(xyDot / (lookVec.lengthVector() * blockProjectedOntoPlayerPlane.lengthVector())); + + Vec3d playerY = lookCross.crossProduct(lookVec); + Vec3d blockProjectedOntoPlayerY = playerY.scale(playerY.dotProduct(toBlock) / playerY.lengthVector()); + Vec3d blockProjectedOntoYawPlane = toBlock.subtract(blockProjectedOntoPlayerY); + double xzDot = lookVec.dotProduct(blockProjectedOntoYawPlane); + double yawTheta = Math.acos(xzDot / (lookVec.lengthVector() * blockProjectedOntoYawPlane.lengthVector())); + + if (Math.abs(Math.toDegrees(yawTheta)) <= Math.min(1, width / height) * (fov / 2.0) && Math.abs(Math.toDegrees(pitchTheta)) <= Math.min(1, height / width) * (fov / 2.0)) + closeTable = true; + } + } + } + + if (closeTable) { + // We are close enough, try crafting recipes + List matching_recipes = CraftingHelper.getRecipesForRequestedOutput(message.parameters); + for (IRecipe recipe : matching_recipes) + if (CraftingHelper.attemptCrafting(player, recipe)) + return null; + } + + return null; + } + } + + @Override + protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { + if (verb.equalsIgnoreCase(SimpleCraftCommand.CRAFT.value())) { + MalmoMod.network.sendToServer(new CraftMessage(parameter)); + return true; + } + return false; + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof NearbyCraftCommands)) + return false; + + craftingTables = new ArrayList(); + + NearbyCraftCommands cParams = (NearbyCraftCommands) params; + setUpAllowAndDenyLists(cParams.getModifierList()); + return true; + } + + @Override + public void install(MissionInit missionInit) { + CraftingHelper.reset(); + } + + @Override + public void deinstall(MissionInit missionInit) { + } + + @Override + public boolean isOverriding() { + return this.isOverriding; + } + + @Override + public void setOverriding(boolean b) { + this.isOverriding = b; + } +} diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java new file mode 100644 index 000000000..1c6aa2e0e --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java @@ -0,0 +1,181 @@ +// -------------------------------------------------------------------------------------------------- +// Copyright (c) 2016 Microsoft Corporation +// +// 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 com.microsoft.Malmo.MissionHandlers; + +import io.netty.buffer.ByteBuf; + +import java.util.ArrayList; + +import net.minecraft.block.BlockFurnace; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.ByteBufUtils; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +import com.microsoft.Malmo.MalmoMod; +import com.microsoft.Malmo.Schemas.MissionInit; +import com.microsoft.Malmo.Schemas.SimpleCraftCommand; +import com.microsoft.Malmo.Schemas.NearbyCraftCommands; +import com.microsoft.Malmo.Utils.CraftingHelper; + +/** + * @author Cayden Codel, Carnegie Mellon University + *

+ * Extends the functionality of the SimpleCraftCommands by requiring a furnace close-by. Only handles smelting, no crafting. + */ +public class NearbySmeltCommandsImplementation extends CommandBase { + private boolean isOverriding; + private static ArrayList furnaces; + + public static class CraftMessage implements IMessage { + String parameters; + + public CraftMessage() { + } + + public CraftMessage(String parameters) { + this.parameters = parameters; + } + + @Override + public void fromBytes(ByteBuf buf) { + this.parameters = ByteBufUtils.readUTF8String(buf); + } + + @Override + public void toBytes(ByteBuf buf) { + ByteBufUtils.writeUTF8String(buf, this.parameters); + } + } + + @SubscribeEvent + public void onBlockPlace(BlockEvent.PlaceEvent event) { + if (!event.isCanceled() && event.getPlacedBlock().getBlock() instanceof BlockFurnace) + furnaces.add(event.getPos()); + } + + @SubscribeEvent + public void onBlockDestroy(BlockEvent.BreakEvent event) { + if (!event.isCanceled() && event.getState().getBlock() instanceof BlockFurnace) + for (int i = furnaces.size() - 1; i >= 0; i--) + if (furnaces.get(i).equals(event.getPos())) + furnaces.remove(i); + } + + public static class CraftMessageHandler implements IMessageHandler { + @Override + public IMessage onMessage(CraftMessage message, MessageContext ctx) { + EntityPlayerMP player = ctx.getServerHandler().playerEntity; + Vec3d headPos = new Vec3d(player.posX, player.posY + 1.6, player.posZ); + + // Location checking + boolean closeFurnace = false; + for (BlockPos furnace : furnaces) { + Vec3d blockVec = new Vec3d(furnace.getX() + 0.5, furnace.getY() + 0.5, furnace.getZ() + 0.5); + + if (headPos.squareDistanceTo(blockVec) <= 25.0) { + // Within a reasonable FOV? + // Lots of trig, let's go + double fov = Minecraft.getMinecraft().gameSettings.fovSetting; + double height = Minecraft.getMinecraft().displayHeight; + double width = Minecraft.getMinecraft().displayWidth; + Vec3d lookVec = player.getLookVec(); + Vec3d toBlock = blockVec.subtract(headPos); + + // Projection of block onto player look vector - if greater than 0, then in front of us + double scalarProjection = lookVec.dotProduct(toBlock) / lookVec.lengthVector(); + if (scalarProjection > 0) { + Vec3d yUnit = new Vec3d(0, 1.0, 0); + Vec3d lookCross = lookVec.crossProduct(yUnit); + Vec3d blockProjectedOntoCross = lookCross.scale(lookCross.dotProduct(toBlock) / lookCross.lengthVector()); + Vec3d blockProjectedOntoPlayerPlane = toBlock.subtract(blockProjectedOntoCross); + double xyDot = lookVec.dotProduct(blockProjectedOntoPlayerPlane); + double pitchTheta = Math.acos(xyDot / (lookVec.lengthVector() * blockProjectedOntoPlayerPlane.lengthVector())); + + Vec3d playerY = lookCross.crossProduct(lookVec); + Vec3d blockProjectedOntoPlayerY = playerY.scale(playerY.dotProduct(toBlock) / playerY.lengthVector()); + Vec3d blockProjectedOntoYawPlane = toBlock.subtract(blockProjectedOntoPlayerY); + double xzDot = lookVec.dotProduct(blockProjectedOntoYawPlane); + double yawTheta = Math.acos(xzDot / (lookVec.lengthVector() * blockProjectedOntoYawPlane.lengthVector())); + + if (Math.abs(Math.toDegrees(yawTheta)) <= Math.min(1, width / height) * (fov / 2.0) && Math.abs(Math.toDegrees(pitchTheta)) <= Math.min(1, height / width) * (fov / 2.0)) + closeFurnace = true; + } + } + } + + if (closeFurnace) { + ItemStack input = CraftingHelper.getSmeltingRecipeForRequestedOutput(message.parameters); + if (input != null) + if (CraftingHelper.attemptSmelting(player, input)) + return null; + } + + return null; + } + } + + @Override + protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { + if (verb.equalsIgnoreCase(SimpleCraftCommand.CRAFT.value())) { + MalmoMod.network.sendToServer(new CraftMessage(parameter)); + return true; + } + return false; + } + + @Override + public boolean parseParameters(Object params) { + furnaces = new ArrayList(); + + if (!(params instanceof NearbyCraftCommands)) + return false; + + NearbyCraftCommands cParams = (NearbyCraftCommands) params; + setUpAllowAndDenyLists(cParams.getModifierList()); + return true; + } + + @Override + public void install(MissionInit missionInit) { + CraftingHelper.reset(); + } + + @Override + public void deinstall(MissionInit missionInit) { + } + + @Override + public boolean isOverriding() { + return this.isOverriding; + } + + @Override + public void setOverriding(boolean b) { + this.isOverriding = b; + } +} \ No newline at end of file diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java index 9eee04e9b..9f3ccc761 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java @@ -82,19 +82,21 @@ private void addSmeltedItemCount(ItemStack is) { } private void checkForMatch(ItemStack is) { + System.out.println("[REWARD] Checking stack " + is.getUnlocalizedName() + " " + is.getCount()); int savedSmelted = getSmeltedItemCount(is); + System.out.println("[REWARD] Previous saved amount is " + savedSmelted); for (ItemMatcher matcher : this.matchers) { if (matcher.matches(is)) { if (!params.isSparse()) { if (savedSmelted != 0 && savedSmelted < matcher.matchSpec.getAmount()) { for (int i = savedSmelted; i < matcher.matchSpec.getAmount() && i - savedSmelted < is.getCount(); i++) { + System.out.println("Giving reward"); this.adjustAndDistributeReward( ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), params.getDimension(), ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); } - } else if (savedSmelted != 0 && savedSmelted >= matcher.matchSpec.getAmount()) { // Do nothing } else { diff --git a/Schemas/Mission.xsd b/Schemas/Mission.xsd index b49ce2bf7..372685c38 100644 --- a/Schemas/Mission.xsd +++ b/Schemas/Mission.xsd @@ -370,6 +370,8 @@ + + diff --git a/Schemas/Mission.xsd.in b/Schemas/Mission.xsd.in index 847715f18..5a76086e6 100644 --- a/Schemas/Mission.xsd.in +++ b/Schemas/Mission.xsd.in @@ -370,6 +370,8 @@ + + diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd index 318b386a0..68095100f 100644 --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -1653,6 +1653,60 @@ + + + + + When present, the Mod will accept simple commands that implement a basic form of crafting. Success of the craft command depends on the presence of a nearby crafting table previously placed by the agent and within reach and in field of view. + + + + + + + + + + + + + + + + + + + + + + + + When present, the Mod will accept simple commands that implement a basic form of smelting. Success of the smelt command depends on the presence of a nearby furnace previously placed by the agent and within reach and in field of view. Fails when a command corresponds to an item not able to be smelted. Each command takes fuel as if the agent had placed the items in a furnace. + + Eg: + + If called on 16 iron ore, requires 2 coal, 2 charcoal, 11 planks, etc. + + If called twice separately on 8 iron ore, requires 1 coal and then 1 coal, etc. + + + + + + + + + + + + + + + + + + + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index 965325d69..b908745cb 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -1653,6 +1653,60 @@ + + + + + When present, the Mod will accept simple commands that implement a basic form of crafting. Success of the craft command depends on the presence of a nearby crafting table previously placed by the agent and within reach and in field of view. + + + + + + + + + + + + + + + + + + + + + + + + When present, the Mod will accept simple commands that implement a basic form of smelting. Success of the smelt command depends on the presence of a nearby furnace previously placed by the agent and within reach and in field of view. Fails when a command corresponds to an item not able to be smelted. Each command takes fuel as if the agent had placed the items in a furnace. + + Eg: + + If called on 16 iron ore, requires 2 coal, 2 charcoal, 11 planks, etc. + + If called twice separately on 8 iron ore, requires 1 coal and then 1 coal, etc. + + + + + + + + + + + + + + + + + + + From 4abdbca3718a196f6ef98cebf3327fc0486d6e57 Mon Sep 17 00:00:00 2001 From: ccodel Date: Wed, 13 Feb 2019 17:06:37 -0500 Subject: [PATCH 07/40] Added some other files I guess --- Malmo/test/PythonTests/malmoutils.py | 103 ++++++++++++++++++ Minecraft/src/main/resources/schemas.index | 5 + .../src/main/resources/version.properties | 1 + 3 files changed, 109 insertions(+) create mode 100644 Malmo/test/PythonTests/malmoutils.py create mode 100644 Minecraft/src/main/resources/schemas.index create mode 100644 Minecraft/src/main/resources/version.properties diff --git a/Malmo/test/PythonTests/malmoutils.py b/Malmo/test/PythonTests/malmoutils.py new file mode 100644 index 000000000..3ff738f75 --- /dev/null +++ b/Malmo/test/PythonTests/malmoutils.py @@ -0,0 +1,103 @@ +# ------------------------------------------------------------------------------------------------ +# Copyright (c) 2016 Microsoft Corporation +# +# 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. +# ------------------------------------------------------------------------------------------------ + +from __future__ import print_function + +# Allow MalmoPython to be imported both from an installed +# malmo module and (as an override) separately as a native library. +try: + import MalmoPython +except ImportError: + import malmo.MalmoPython as MalmoPython + +import os +import sys +import errno + +def fix_print(): + # We want to flush the print output immediately, so that we can view test output as it happens. + # The way to do this changed completely between Python 2 and 3, with the result that setting this + # in a cross-compatible way requires a few lines of ugly code. + # Rather than include this mess in every single sample, it's nice to wrap it into a handy + # function - hence this. + if sys.version_info[0] == 2: + sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) # flush print output immediately + else: + import functools + # Have to assign to builtins or the change won't make it outside of this module's scope + import builtins + builtins.print = functools.partial(print, flush=True) + +def parse_command_line(agent_host, argv=None): + if argv is None: + argv = sys.argv + # Add standard options required by test suite: + agent_host.addOptionalStringArgument( "recording_dir,r", "Path to location for saving mission recordings", "" ) + agent_host.addOptionalFlag( "record_video,v", "Record video stream" ) + # Attempt to parse: + try: + agent_host.parse(argv) + except RuntimeError as e: + print('ERROR:',e) + print(agent_host.getUsage()) + exit(1) + if agent_host.receivedArgument("help"): + print(agent_host.getUsage()) + exit(0) + + +def get_video_xml(agent_host): + return '860480' if agent_host.receivedArgument("record_video") else '' + +def get_default_recording_object(agent_host, filename): + # Convenience method for setting up a recording object - assuming the recording_dir and record_video + # flags were passed in as command line arguments (see parse_command_line above). + # (If no recording destination was passed in, we assume no recording is required.) + my_mission_record = MalmoPython.MissionRecordSpec() + recordingsDirectory = get_recordings_directory(agent_host) + if recordingsDirectory: + my_mission_record.setDestination(recordingsDirectory + "//" + filename + ".tgz") + my_mission_record.recordRewards() + my_mission_record.recordObservations() + my_mission_record.recordCommands() + if agent_host.receivedArgument("record_video"): + my_mission_record.recordMP4(24,2000000) + return my_mission_record + +def get_recordings_directory(agent_host): + # Check the dir passed in: + recordingsDirectory = agent_host.getStringArgument('recording_dir') + if recordingsDirectory: + # If we're running as an integration test, we want to send all our recordings + # to the central test location specified in the environment variable MALMO_TEST_RECORDINGS_PATH: + if agent_host.receivedArgument("test"): + try: + test_path = os.environ['MALMO_TEST_RECORDINGS_PATH'] + if test_path: + recordingsDirectory = os.path.join(test_path, recordingsDirectory) + except: + pass + # Now attempt to create the folder we want to write to: + try: + os.makedirs(recordingsDirectory) + except OSError as exception: + if exception.errno != errno.EEXIST: # ignore error if already existed + raise + return recordingsDirectory + diff --git a/Minecraft/src/main/resources/schemas.index b/Minecraft/src/main/resources/schemas.index new file mode 100644 index 000000000..55dcedb71 --- /dev/null +++ b/Minecraft/src/main/resources/schemas.index @@ -0,0 +1,5 @@ +MissionHandlers.xsd +MissionInit.xsd +MissionEnded.xsd +Types.xsd +Mission.xsd diff --git a/Minecraft/src/main/resources/version.properties b/Minecraft/src/main/resources/version.properties new file mode 100644 index 000000000..4beb6b3b9 --- /dev/null +++ b/Minecraft/src/main/resources/version.properties @@ -0,0 +1 @@ +malmomod.version= 0.36.0 From e60eb60a6e27096025d61058d3f037d27b45ba4a Mon Sep 17 00:00:00 2001 From: ccodel Date: Wed, 13 Feb 2019 17:06:54 -0500 Subject: [PATCH 08/40] One more too --- Minecraft/run/options.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Minecraft/run/options.txt b/Minecraft/run/options.txt index 125a28e9d..8c80f9f8c 100644 --- a/Minecraft/run/options.txt +++ b/Minecraft/run/options.txt @@ -1,7 +1,7 @@ version:922 invertYMouse:false mouseSensitivity:0.5 -fov:0.0 +fov:0.5 gamma:0.0 saturation:0.0 renderDistance:6 From 40d3724b9f6608c2ce7f1903a0861e61fa182ac1 Mon Sep 17 00:00:00 2001 From: William Guss Date: Sun, 17 Feb 2019 23:46:51 -0500 Subject: [PATCH 09/40] Updating agent host. --- Malmo/src/AgentHost.cpp | 3 ++- .../java/com/microsoft/Malmo/Client/ClientStateMachine.java | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Malmo/src/AgentHost.cpp b/Malmo/src/AgentHost.cpp index 3553a804d..853e6a784 100755 --- a/Malmo/src/AgentHost.cpp +++ b/Malmo/src/AgentHost.cpp @@ -897,9 +897,10 @@ namespace malmo if( !this->commands_connection ) { TimestampedString error_message( boost::posix_time::microsec_clock::universal_time(), - "AgentHost::sendCommand : commands connection is not open. Is the mission running?" + "AgentHost::sendCommand : commands connection is not open. Attempting to start a new commands connection." ); this->world_state.errors.push_back( boost::make_shared( error_message ) ); + this->openCommandsConnection(); return; } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/Client/ClientStateMachine.java b/Minecraft/src/main/java/com/microsoft/Malmo/Client/ClientStateMachine.java index c3c659f84..6d4b1c473 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/Client/ClientStateMachine.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/Client/ClientStateMachine.java @@ -955,6 +955,7 @@ protected void execute() throws Exception { // A specific port has been requested, and it's not the one we are currently using, // so we need to recreate our poller. + System.out.println("Requested command port is not the same as the input poller port; the port was not free. Stopping server."); ClientStateMachine.this.controlInputPoller.stopServer(); ClientStateMachine.this.controlInputPoller = null; } @@ -964,6 +965,7 @@ protected void execute() throws Exception ClientStateMachine.this.controlInputPoller = new TCPInputPoller(AddressHelper.MIN_FREE_PORT, AddressHelper.MAX_FREE_PORT, true, "com"); else ClientStateMachine.this.controlInputPoller = new TCPInputPoller(requestedPort, "com"); + System.out.println("Starting command server."); ClientStateMachine.this.controlInputPoller.start(); } // Make sure the cac is up-to-date: From 553ca513735f45f720ebf7a0116b416207322ea1 Mon Sep 17 00:00:00 2001 From: Phillip Date: Mon, 18 Feb 2019 22:02:14 -0500 Subject: [PATCH 10/40] Fix bug with navigate teleport --- ...anceTraveledToCompassTargetImplementation.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForDistanceTraveledToCompassTargetImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForDistanceTraveledToCompassTargetImplementation.java index d0ee7ec3e..efb1d3a34 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForDistanceTraveledToCompassTargetImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForDistanceTraveledToCompassTargetImplementation.java @@ -1,5 +1,7 @@ package com.microsoft.Malmo.MissionHandlers; +import java.lang.*; + import com.microsoft.Malmo.Schemas.MissionInit; import com.microsoft.Malmo.Schemas.RewardForDistanceTraveledToCompassTarget; @@ -14,6 +16,7 @@ public class RewardForDistanceTraveledToCompassTargetImplementation extends Rewa double previousDistance; float totalReward; boolean positionInitialized; + BlockPos spawn; @Override public boolean parseParameters(Object params) @@ -25,7 +28,7 @@ public boolean parseParameters(Object params) this.params = (RewardForDistanceTraveledToCompassTarget)params; EntityPlayerSP player = Minecraft.getMinecraft().player; - BlockPos spawn = player.world.getSpawnPoint(); + spawn = player.world.getSpawnPoint(); BlockPos playerLoc = player.getPosition(); this.previousDistance = playerLoc.getDistance(spawn.getX(), spawn.getY(), spawn.getZ()); @@ -41,11 +44,10 @@ public void getReward(MissionInit missionInit, MultidimensionalReward reward) boolean sendReward = false; EntityPlayerSP player = Minecraft.getMinecraft().player; - BlockPos spawn = player.world.getSpawnPoint(); BlockPos playerLoc = player.getPosition(); double currentDistance = playerLoc.getDistance(spawn.getX(), spawn.getY(), spawn.getZ()); - float delta = -1 * (float)(currentDistance - previousDistance); + float delta = (float)(this.previousDistance - currentDistance); switch (this.params.getDensity()) { case MISSION_END: @@ -65,12 +67,13 @@ public void getReward(MissionInit missionInit, MultidimensionalReward reward) } // Avoid sending large rewards as the result of an initial teleport event - if(!this.positionInitialized && (delta < -0.0001 || 0.0001 < delta)){ - this.positionInitialized = true; + if(!this.positionInitialized && Math.abs(delta) > 0.0001) { this.totalReward = 0; + } else { + this.positionInitialized = true; } - this.previousDistance = playerLoc.getDistance(spawn.getX(), spawn.getY(), spawn.getZ()); + this.previousDistance = currentDistance; super.getReward(missionInit, reward); if (sendReward) From 3afbd4130e1c796cc8763ead2ed703b0ce590626 Mon Sep 17 00:00:00 2001 From: ccodel Date: Tue, 19 Feb 2019 19:10:39 -0500 Subject: [PATCH 11/40] Added place commands, not yet tested --- CMakeLists.txt | 16 +- Malmo/src/MissionSpec.cpp | 9 + Malmo/src/MissionSpec.h | 4 + ...tQuitFromPossessingItemImplementation.java | 322 +++++++++--------- .../PlaceCommandsImplementation.java | 132 +++++++ Minecraft/src/main/resources/schemas.index | 4 +- Schemas/MissionHandlers.xsd | 51 ++- Schemas/MissionHandlers.xsd.in | 48 +++ 8 files changed, 415 insertions(+), 171 deletions(-) create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java diff --git a/CMakeLists.txt b/CMakeLists.txt index f3bdd4165..d8fb4e997 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,9 +51,10 @@ set( STATIC_BOOST ON CACHE BOOL ${STATIC_BOOST_DESC} ) if( INCLUDE_PYTHON ) set( USE_PYTHON_VERSIONS_DESC "Specifies which version of Python to build Malmo with Python bindings" ) + set( MACOS_USE_PYTHON_MODULE_DESC "Specifies which Python module to build Malmo on Apple MacOS" ) set( USE_PYTHON_VERSIONS 3.6 CACHE STRING ${USE_PYTHON_VERSIONS_DESC} ) - set( BOOST_PYTHON_NAME_DESC "Specifies which Boost Python module to build Malmo with" ) - set( BOOST_PYTHON_NAME "python3" CACHE STRING ${BOOST_PYTHON_NAME_DESC} ) + # Boost has switched to using a 2 digit naming convention for python on MacOS. + set( MACOS_USE_PYTHON_MODULE "python37" CACHE STRING ${MACOS_USE_PYTHON_MODULE_DESC} ) endif() set( WARNINGS_AS_ERRORS OFF ) @@ -105,18 +106,21 @@ SET(Boost_ADDITIONAL_VERSIONS "1.67" "1.67.0") SET(BOOST_PYTHON_MODULE_NAME "python") if ( USE_PYTHON_VERSIONS VERSION_GREATER 3 ) - SET( BOOST_PYTHON_MODULE_NAME ${BOOST_PYTHON_NAME} ) + if ( APPLE ) + SET( BOOST_PYTHON_MODULE_NAME ${MACOS_USE_PYTHON_MODULE} ) + else() + SET( BOOST_PYTHON_MODULE_NAME "python3" ) + endif() endif() if( WIN32 ) SET(Boost_USE_STATIC_LIBS ON) - find_package( Boost COMPONENTS chrono date_time filesystem iostreams program_options ${BOOST_PYTHON_MODULE_NAME} regex system thread REQUIRED ) - add_definitions(-DBOOST_ALL_NO_LIB=1) # Turn off auto-linking, creates problems when linking boost statically + find_package( Boost COMPONENTS chrono date_time filesystem iostreams program_options ${BOOST_PYTHON_MODULE_NAME} regex system thread zlib REQUIRED ) else() - SET(Boost_USE_STATIC_LIBS ${STATIC_BOOST}) find_package( Boost COMPONENTS chrono date_time filesystem iostreams program_options ${BOOST_PYTHON_MODULE_NAME} regex system thread REQUIRED ) set(CMAKE_THREAD_PREFER_PTHREAD TRUE) find_package( Threads REQUIRED ) + SET(Boost_USE_STATIC_LIBS ${STATIC_BOOST}) endif() # suggested install paths - see readme.md diff --git a/Malmo/src/MissionSpec.cpp b/Malmo/src/MissionSpec.cpp index ca56c3212..a274b42b7 100755 --- a/Malmo/src/MissionSpec.cpp +++ b/Malmo/src/MissionSpec.cpp @@ -384,6 +384,7 @@ namespace malmo child.erase("SimpleCraftCommands"); child.erase("NearbyCraftCommands"); child.erase("NearbySmeltCommands"); + child.erase("PlaceCommands"); child.erase("ChatCommands"); child.erase("MissionQuitCommands"); } @@ -433,6 +434,11 @@ namespace malmo { mission.put("Mission.AgentSection.AgentHandlers.ChatCommands", ""); } + + void MissionSpec::allowAllPlaceCommands() + { + mission.put("Mission.AgentSection.AgentHandlers.PlaceCommands", ""); + } // ------------------------------- information --------------------------------------------------- @@ -536,6 +542,9 @@ namespace malmo if (e.second.get_child_optional("AgentHandlers.NearbySmeltCommands")) command_handlers.push_back("NearbySmelt"); + + if (e.second.get_child_optional("AgentHandlers.PlaceCommands")) + command_handlers.push_back("Place"); if (e.second.get_child_optional("AgentHandlers.MissionQuitCommands")) command_handlers.push_back("MissionQuit"); diff --git a/Malmo/src/MissionSpec.h b/Malmo/src/MissionSpec.h index 5804f0b0e..c5f644927 100755 --- a/Malmo/src/MissionSpec.h +++ b/Malmo/src/MissionSpec.h @@ -299,6 +299,10 @@ namespace malmo //! Only applies to the first agent in the mission. For multi-agent missions, specify the command handlers for each in the XML. void allowAllChatCommands(); + //! Adds a place command handler if none present, with neither an allow-list or a deny-list, thus allowing any command to be sent. + //! Only applies to the first agent in the mission. For multi-agent missions, specify the command handlers for each in the XML. + void allowAllPlaceCommands(); + // ------------------------- information -------------------------------------- //! Returns the short description of the mission. diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java index 1629cf061..717164a33 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java @@ -28,165 +28,165 @@ */ public class AgentQuitFromPossessingItemImplementation extends HandlerBase implements IWantToQuit { - private AgentQuitFromPossessingItem params; - private HashMap collectedItems; - private List matchers; - private String quitCode = ""; - private boolean wantToQuit = false; - - public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { - String description; - - ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { - super(spec); - this.description = spec.getDescription(); - } - - String description() { - return this.description; - } - } - - @Override - public boolean parseParameters(Object params) { - if (!(params instanceof AgentQuitFromPossessingItem)) - return false; - - this.params = (AgentQuitFromPossessingItem) params; - this.matchers = new ArrayList(); - for (BlockOrItemSpecWithDescription bs : this.params.getItem()) - this.matchers.add(new ItemQuitMatcher(bs)); - return true; - } - - @Override - public boolean doIWantToQuit(MissionInit missionInit) { - return this.wantToQuit; - } - - @Override - public String getOutcome() { - return this.quitCode; - } - - @Override - public void prepare(MissionInit missionInit) { - MinecraftForge.EVENT_BUS.register(this); - collectedItems = new HashMap(); - } - - @Override - public void cleanup() { - MinecraftForge.EVENT_BUS.unregister(this); - } - - @SubscribeEvent - public void onGainItem(GainItemEvent event) { - checkForMatch(event.stack); - } - - @SubscribeEvent - public void onPickupItem(EntityItemPickupEvent event) { - if (event.getItem() != null) - checkForMatch(event.getItem().getEntityItem()); - } - - @SubscribeEvent - public void onLoseItem(LoseItemEvent event) { - if (event.stack != null) - removeCollectedItemCount(event.stack); - } - - @SubscribeEvent - public void onDropItem(ItemTossEvent event) { - removeCollectedItemCount(event.getEntityItem().getEntityItem()); - } - - @SubscribeEvent - public void onDestroyItem(PlayerDestroyItemEvent event) { - removeCollectedItemCount(event.getOriginal()); - } - - @SubscribeEvent - public void onBlockPlace(PlaceEvent event) { - if (!event.isCanceled() && event.getPlacedBlock() != null) { - ItemStack stack = new ItemStack(event.getPlacedBlock().getBlock()); - removeCollectedItemCount(stack); - } - } - - /** - * Checks whether the ItemStack matches a variant stored in the item list. If - * so, returns true, else returns false. - * - * @param is The item stack - * @return If the stack is allowed in the item matchers and has color or - * variants enabled, returns true, else false. - */ - private boolean getVariant(ItemStack is) { - for (ItemQuitMatcher matcher : matchers) { - if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { - if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) - return true; - if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) - return true; - } - } - - return false; - } - - private void addCollectedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getUnlocalizedName())); - if (variant) - collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - else - collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - - } - - private void removeCollectedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getUnlocalizedName())); - if (variant) - collectedItems.put(is.getUnlocalizedName(), prev - is.getCount()); - else - collectedItems.put(is.getItem().getUnlocalizedName(), prev - is.getCount()); - } - - private int getCollectedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) - return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 : collectedItems.get(is.getUnlocalizedName()); - else - return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 - : collectedItems.get(is.getItem().getUnlocalizedName()); - } - - private void checkForMatch(ItemStack is) { - int savedCollected = getCollectedItemCount(is); - if (is != null) { - for (ItemQuitMatcher matcher : this.matchers) { - if (matcher.matches(is)) { - if (savedCollected != 0) { - if (is.getCount() + savedCollected >= matcher.matchSpec.getAmount()) { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } else if (is.getCount() >= matcher.matchSpec.getAmount()) { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } - } - - addCollectedItemCount(is); - } - } + private AgentQuitFromPossessingItem params; + private HashMap collectedItems; + private List matchers; + private String quitCode = ""; + private boolean wantToQuit = false; + + public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { + String description; + + ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { + super(spec); + this.description = spec.getDescription(); + } + + String description() { + return this.description; + } + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof AgentQuitFromPossessingItem)) + return false; + + this.params = (AgentQuitFromPossessingItem) params; + this.matchers = new ArrayList(); + for (BlockOrItemSpecWithDescription bs : this.params.getItem()) + this.matchers.add(new ItemQuitMatcher(bs)); + return true; + } + + @Override + public boolean doIWantToQuit(MissionInit missionInit) { + return this.wantToQuit; + } + + @Override + public String getOutcome() { + return this.quitCode; + } + + @Override + public void prepare(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.register(this); + collectedItems = new HashMap(); + } + + @Override + public void cleanup() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void onGainItem(GainItemEvent event) { + checkForMatch(event.stack); + } + + @SubscribeEvent + public void onPickupItem(EntityItemPickupEvent event) { + if (event.getItem() != null) + checkForMatch(event.getItem().getEntityItem()); + } + + @SubscribeEvent + public void onLoseItem(LoseItemEvent event) { + if (event.stack != null) + removeCollectedItemCount(event.stack); + } + + @SubscribeEvent + public void onDropItem(ItemTossEvent event) { + removeCollectedItemCount(event.getEntityItem().getEntityItem()); + } + + @SubscribeEvent + public void onDestroyItem(PlayerDestroyItemEvent event) { + removeCollectedItemCount(event.getOriginal()); + } + + @SubscribeEvent + public void onBlockPlace(PlaceEvent event) { + if (!event.isCanceled() && event.getPlacedBlock() != null) { + ItemStack stack = new ItemStack(event.getPlacedBlock().getBlock()); + removeCollectedItemCount(stack); + } + } + + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ + private boolean getVariant(ItemStack is) { + for (ItemQuitMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private void addCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + if (variant) + collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + else + collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + + } + + private void removeCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + if (variant) + collectedItems.put(is.getUnlocalizedName(), prev - is.getCount()); + else + collectedItems.put(is.getItem().getUnlocalizedName(), prev - is.getCount()); + } + + private int getCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 : collectedItems.get(is.getUnlocalizedName()); + else + return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName()); + } + + private void checkForMatch(ItemStack is) { + int savedCollected = getCollectedItemCount(is); + if (is != null) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedCollected != 0) { + if (is.getCount() + savedCollected >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } + } + + addCollectedItemCount(is); + } + } } \ No newline at end of file diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java new file mode 100644 index 000000000..470bc607f --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java @@ -0,0 +1,132 @@ +// -------------------------------------------------------------------------------------------------- +// Copyright (c) 2016 Microsoft Corporation +// +// 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 com.microsoft.Malmo.MissionHandlers; + +import com.microsoft.Malmo.Schemas.*; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; + +import com.microsoft.Malmo.MissionHandlerInterfaces.ICommandHandler; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraftforge.common.util.BlockSnapshot; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.common.MinecraftForge; + +/** + * @author Cayden Codel, Carnegie Mellon University + *

+ * Place commands allow agents to place blocks in the world without having to worry about inventory management. + */ +public class PlaceCommandsImplementation extends CommandBase implements ICommandHandler { + private boolean isOverriding; + + @Override + protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { + EntityPlayerSP player = Minecraft.getMinecraft().player; + if (player == null) + return false; + + if (!verb.equalsIgnoreCase(PlaceCommand.PLACE.value())) + return false; + + InventoryPlayer inv = player.inventory; + Block b = Block.getBlockFromName(parameter); + if (b == null || b.getRegistryName() == null) + return false; + + boolean foundBlock = false; + for (int i = 0; i < 41 && !foundBlock; i++) { + ItemStack s = inv.getStackInSlot(i).copy(); + if (b.getRegistryName().equals(s.getItem().getRegistryName())) { + int selectedHotBarItem = inv.currentItem; + ItemStack selected = inv.getStackInSlot(selectedHotBarItem).copy(); + inv.setInventorySlotContents(selectedHotBarItem, s); + inv.setInventorySlotContents(i, selected); + + RayTraceResult mop = Minecraft.getMinecraft().objectMouseOver; + if (mop.typeOfHit == RayTraceResult.Type.BLOCK) { + BlockPos pos = mop.getBlockPos().add(mop.sideHit.getDirectionVec()); + // Can we place this block here? + AxisAlignedBB axisalignedbb = b.getDefaultState().getCollisionBoundingBox(player.world, pos); + if (axisalignedbb == null) { + PlayerInteractEvent event = new PlayerInteractEvent.RightClickBlock(player, EnumHand.MAIN_HAND, mop.getBlockPos(), mop.sideHit, mop.hitVec); + MinecraftForge.EVENT_BUS.post(event); + if (!event.isCanceled()) { + BlockPos newPos = mop.getBlockPos().add(mop.sideHit.getDirectionVec()); + Block newB = Block.getBlockFromItem(inv.getCurrentItem().getItem()); + IBlockState blockType = newB.getStateFromMeta(inv.getCurrentItem().getMetadata()); + if (player.world.setBlockState(newPos, blockType)) { + BlockSnapshot snapshot = new BlockSnapshot(player.world, newPos, blockType); + BlockEvent.PlaceEvent placeEvent = new BlockEvent.PlaceEvent(snapshot, player.world.getBlockState(mop.getBlockPos()), player, EnumHand.MAIN_HAND); + MinecraftForge.EVENT_BUS.post(placeEvent); + // We set the block, so remove it from the inventory. + if (!player.isCreative()) { + if (player.inventory.getCurrentItem().getCount() > 1) + player.inventory.getCurrentItem().setCount(player.inventory.getCurrentItem().getCount() - 1); + else + player.inventory.mainInventory.get(player.inventory.currentItem).setCount(0); + } + } + } + } + } + foundBlock = true; + } + } + + return true; + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof PlaceCommands)) + return false; + + PlaceCommands pParams = (PlaceCommands) params; + setUpAllowAndDenyLists(pParams.getModifierList()); + return true; + } + + @Override + public void install(MissionInit missionInit) { + } + + @Override + public void deinstall(MissionInit missionInit) { + } + + @Override + public boolean isOverriding() { + return this.isOverriding; + } + + @Override + public void setOverriding(boolean b) { + this.isOverriding = b; + } +} \ No newline at end of file diff --git a/Minecraft/src/main/resources/schemas.index b/Minecraft/src/main/resources/schemas.index index 70b4a99d8..55dcedb71 100644 --- a/Minecraft/src/main/resources/schemas.index +++ b/Minecraft/src/main/resources/schemas.index @@ -1,5 +1,5 @@ -Mission.xsd -MissionEnded.xsd MissionHandlers.xsd MissionInit.xsd +MissionEnded.xsd Types.xsd +Mission.xsd diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd index b82bfe4f8..52d78a55a 100644 --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -1066,9 +1066,7 @@ Sets whether or not the compass location should be randomized within a certain radius. - If false, will set the compass location to the block that was randomly placed. - If true, will set the compass location to a random spot within the radius specified below. @@ -1464,6 +1462,27 @@ + + + + + A command for placing blocks in the agent's inventory: + + Will look in the agent's inventory. If the block exists, will try to place the block in the world. + + For basic objects, use BlockTypes found in Types.xsd. Eg: + + "{{{place diamond_block}}}" will attempt to place a diamond block from the agent's inventory. + + for more control over colours, types, etc, add a Variation or Colour. Eg: + + "{{{place carpet PINK}}}" + + + + + + @@ -1741,6 +1760,33 @@ + + + + + When present, the Mod will accept commands that allow for the placement of blocks. If the specified block is contained in the agent's inventory, then the agent will attempt to place the block in the world. + + If a non-block is specified, the command fails. + + If a block is specified, the block will swap to the hotbar, be placed, and then swapped back, so no changes to the inventory are made besides losing a block. + + + + + + + + + + + + + + + + + + @@ -2110,6 +2156,7 @@ + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index 21c67a619..c3359a536 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -1462,6 +1462,27 @@ + + + + + A command for placing blocks in the agent's inventory: + + Will look in the agent's inventory. If the block exists, will try to place the block in the world. + + For basic objects, use BlockTypes found in Types.xsd. Eg: + + "{{{place diamond_block}}}" will attempt to place a diamond block from the agent's inventory. + + for more control over colours, types, etc, add a Variation or Colour. Eg: + + "{{{place carpet PINK}}}" + + + + + + @@ -1739,6 +1760,33 @@ + + + + + When present, the Mod will accept commands that allow for the placement of blocks. If the specified block is contained in the agent's inventory, then the agent will attempt to place the block in the world. + + If a non-block is specified, the command fails. + + If a block is specified, the block will swap to the hotbar, be placed, and then swapped back, so no changes to the inventory are made besides losing a block. + + + + + + + + + + + + + + + + + + From c9c9e330bf64d3d8c919016f62bc5336847a617a Mon Sep 17 00:00:00 2001 From: ccodel Date: Tue, 19 Feb 2019 19:14:09 -0500 Subject: [PATCH 12/40] Swapped items back --- .../Malmo/MissionHandlers/PlaceCommandsImplementation.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java index 470bc607f..3cb3bfe6a 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java @@ -66,7 +66,6 @@ protected boolean onExecute(String verb, String parameter, MissionInit missionIn int selectedHotBarItem = inv.currentItem; ItemStack selected = inv.getStackInSlot(selectedHotBarItem).copy(); inv.setInventorySlotContents(selectedHotBarItem, s); - inv.setInventorySlotContents(i, selected); RayTraceResult mop = Minecraft.getMinecraft().objectMouseOver; if (mop.typeOfHit == RayTraceResult.Type.BLOCK) { @@ -96,6 +95,9 @@ protected boolean onExecute(String verb, String parameter, MissionInit missionIn } } foundBlock = true; + + inv.setInventorySlotContents(i, inv.getCurrentItem()); + inv.setInventorySlotContents(selectedHotBarItem, selected); } } From b88a7eb0ceb904325fac9e95e4cdd0de231ecf83 Mon Sep 17 00:00:00 2001 From: William Guss Date: Wed, 20 Feb 2019 16:44:51 -0500 Subject: [PATCH 13/40] Updatting fixe. --- Malmo/samples/Python_examples/Untitled-1 | 63 +++++++++++++++++++ Malmo/samples/Python_examples/navigation.xml | 61 ++++++++++++++++++ Malmo/samples/Python_examples/run_mission.py | 20 ++++-- ...TraveledToCompassTargetImplementation.java | 7 ++- 4 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 Malmo/samples/Python_examples/Untitled-1 create mode 100644 Malmo/samples/Python_examples/navigation.xml diff --git a/Malmo/samples/Python_examples/Untitled-1 b/Malmo/samples/Python_examples/Untitled-1 new file mode 100644 index 000000000..84df10b44 --- /dev/null +++ b/Malmo/samples/Python_examples/Untitled-1 @@ -0,0 +1,63 @@ +agent_host = MalmoPython.AgentHost() +try: + agent_host.parse( sys.argv ) +except RuntimeError as e: + print('ERROR:',e) + print(agent_host.getUsage()) + exit(1) +if agent_host.receivedArgument("help"): + print(agent_host.getUsage()) + exit(0) + +# -- set up the mission -- # +mission_file = './tutorial_6.xml' +with open(mission_file, 'r') as f: + print("Loading mission from %s" % mission_file) + mission_xml = f.read() + my_mission = MalmoPython.MissionSpec(mission_xml, True) +# add 20% holes for interest +for x in range(1,4): + for z in range(1,13): + if random.random()<0.1: + my_mission.drawBlock( x,45,z,"lava") + +max_retries = 3 + +if agent_host.receivedArgument("test"): + num_repeats = 1 +else: + num_repeats = 150 + +cumulative_rewards = [] +for i in range(num_repeats): + + print() + print('Repeat %d of %d' % ( i+1, num_repeats )) + + my_mission_record = MalmoPython.MissionRecordSpec() + + for retry in range(max_retries): + try: + agent_host.startMission( my_mission, my_mission_record ) + break + except RuntimeError as e: + if retry == max_retries - 1: + print("Error starting mission:",e) + exit(1) + else: + time.sleep(2.5) + + print("Waiting for the mission to start", end=' ') + world_state = agent_host.getWorldState() + while not world_state.has_mission_begun: + print(".", end="") + time.sleep(0.1) + world_state = agent_host.getWorldState() + for error in world_state.errors: + print("Error:",error.text) + print() + + # -- run the agent in the world -- # + cumulative_reward = agent.run(agent_host) + print('Cumulative reward: %d' % cumulative_reward) + cumulative_rewards += [ cumulative_reward ] diff --git a/Malmo/samples/Python_examples/navigation.xml b/Malmo/samples/Python_examples/navigation.xml new file mode 100644 index 000000000..c8bf71c12 --- /dev/null +++ b/Malmo/samples/Python_examples/navigation.xml @@ -0,0 +1,61 @@ + + + +

Navigation through survival world. + + + + 50 + + + + + + clear + false + + + + + + 64 + 64 + diamond_block + surface + + true + 0 + 1 + + + + + + + + Columbus + + + + + + + + + + + + + + + + + + + + + + diff --git a/Malmo/samples/Python_examples/run_mission.py b/Malmo/samples/Python_examples/run_mission.py index ac20b5c77..247adab08 100755 --- a/Malmo/samples/Python_examples/run_mission.py +++ b/Malmo/samples/Python_examples/run_mission.py @@ -58,11 +58,15 @@ def run(argv=['']): agent_host = MalmoPython.AgentHost() malmoutils.parse_command_line(agent_host, argv) + with open('navigation.xml', 'r') as f: + print("Loading mission from %s" % 'navigation.xml') + mission_xml = f.read() + my_mission = MalmoPython.MissionSpec(mission_xml, True) - my_mission = MalmoPython.MissionSpec() - my_mission.timeLimitInSeconds( 10 ) - my_mission.requestVideo( 320, 240 ) - my_mission.rewardForReachingPosition( 19.5, 0.0, 19.5, 100.0, 1.1 ) + # my_mission = MalmoPython.MissionSpec() + # my_mission.timeLimitInSeconds( 10 ) + # my_mission.requestVideo( 320, 240 ) + # my_mission.rewardForReachingPosition( 19.5, 0.0, 19.5, 100.0, 1.1 ) my_mission_record = malmoutils.get_default_recording_object(agent_host, "saved_data") @@ -103,6 +107,7 @@ def run(argv=['']): print() last_delta = time.time() + net_reward = 00 # main loop: while world_state.is_mission_running: agent_host.sendCommand( "move 1" ) @@ -119,14 +124,17 @@ def run(argv=['']): print("Max delay exceeded for world state change") restart_minecraft(world_state, agent_host, client_info, "world state change") for reward in world_state.rewards: - print("Summed reward:",reward.getValue()) + cur_r = reward.getValue() + print("Summed reward:",cur_r) + net_reward += cur_r + print(net_reward) for error in world_state.errors: print("Error:",error.text) for frame in world_state.video_frames: print("Frame:",frame.width,'x',frame.height,':',frame.channels,'channels') #image = Image.frombytes('RGB', (frame.width, frame.height), bytes(frame.pixels) ) # to convert to a PIL image print("Mission has stopped.") - + print("FINAL REWARD: {}".format(net_reward)) if __name__ == "__main__": run(sys.argv) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForDistanceTraveledToCompassTargetImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForDistanceTraveledToCompassTargetImplementation.java index efb1d3a34..dedccc392 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForDistanceTraveledToCompassTargetImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForDistanceTraveledToCompassTargetImplementation.java @@ -9,6 +9,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; public class RewardForDistanceTraveledToCompassTargetImplementation extends RewardBase { @@ -44,9 +45,11 @@ public void getReward(MissionInit missionInit, MultidimensionalReward reward) boolean sendReward = false; EntityPlayerSP player = Minecraft.getMinecraft().player; - BlockPos playerLoc = player.getPosition(); + spawn = player.world.getSpawnPoint(); + Vec3d playerLoc = player.getPositionVector(); + Vec3d spawnPos = new Vec3d(spawn.getX(), spawn.getY(), spawn.getZ()); - double currentDistance = playerLoc.getDistance(spawn.getX(), spawn.getY(), spawn.getZ()); + double currentDistance = playerLoc.distanceTo(spawnPos); float delta = (float)(this.previousDistance - currentDistance); switch (this.params.getDensity()) { From 03210785611f0a7b12983e1b401c4fc80058cc2d Mon Sep 17 00:00:00 2001 From: Phillip Date: Wed, 20 Feb 2019 18:11:29 -0500 Subject: [PATCH 14/40] Fix from teleport check to spawn change check --- ...anceTraveledToCompassTargetImplementation.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForDistanceTraveledToCompassTargetImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForDistanceTraveledToCompassTargetImplementation.java index dedccc392..9f9e584db 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForDistanceTraveledToCompassTargetImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForDistanceTraveledToCompassTargetImplementation.java @@ -17,7 +17,7 @@ public class RewardForDistanceTraveledToCompassTargetImplementation extends Rewa double previousDistance; float totalReward; boolean positionInitialized; - BlockPos spawn; + BlockPos prevSpawn; @Override public boolean parseParameters(Object params) @@ -29,9 +29,9 @@ public boolean parseParameters(Object params) this.params = (RewardForDistanceTraveledToCompassTarget)params; EntityPlayerSP player = Minecraft.getMinecraft().player; - spawn = player.world.getSpawnPoint(); + prevSpawn = player.world.getSpawnPoint(); BlockPos playerLoc = player.getPosition(); - this.previousDistance = playerLoc.getDistance(spawn.getX(), spawn.getY(), spawn.getZ()); + this.previousDistance = playerLoc.getDistance(prevSpawn.getX(), prevSpawn.getY(), prevSpawn.getZ()); this.totalReward = 0; this.positionInitialized = false; @@ -45,7 +45,7 @@ public void getReward(MissionInit missionInit, MultidimensionalReward reward) boolean sendReward = false; EntityPlayerSP player = Minecraft.getMinecraft().player; - spawn = player.world.getSpawnPoint(); + BlockPos spawn = player.world.getSpawnPoint(); Vec3d playerLoc = player.getPositionVector(); Vec3d spawnPos = new Vec3d(spawn.getX(), spawn.getY(), spawn.getZ()); @@ -70,13 +70,14 @@ public void getReward(MissionInit missionInit, MultidimensionalReward reward) } // Avoid sending large rewards as the result of an initial teleport event - if(!this.positionInitialized && Math.abs(delta) > 0.0001) { + if (this.prevSpawn.getX() != spawn.getX() || + this.prevSpawn.getY() != spawn.getY() || + this.prevSpawn.getZ() != spawn.getZ()) { this.totalReward = 0; - } else { - this.positionInitialized = true; } this.previousDistance = currentDistance; + this.prevSpawn = spawn; super.getReward(missionInit, reward); if (sendReward) From a12f533b572395db0694114a4db88ebfacd80cd9 Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Thu, 21 Feb 2019 22:18:42 -0500 Subject: [PATCH 15/40] Updated commands for cayden's new handlers --- Malmo/samples/samples.iml | 22 +++++++++ Malmo/src/MissionSpec.cpp | 4 +- .../java/com/microsoft/Malmo/MalmoMod.java | 5 +++ .../NearbyCraftCommandsImplementation.java | 4 +- .../NearbySmeltCommandsImplementation.java | 10 ++--- Minecraft/src/main/resources/schemas.index | 4 +- Schemas/MissionHandlers.xsd | 40 +++++++++++++---- Schemas/MissionHandlers.xsd.in | 45 ++++++++++++++++--- Schemas/Schemas.iml | 9 ++++ 9 files changed, 116 insertions(+), 27 deletions(-) create mode 100644 Malmo/samples/samples.iml create mode 100644 Schemas/Schemas.iml diff --git a/Malmo/samples/samples.iml b/Malmo/samples/samples.iml new file mode 100644 index 000000000..722c9789b --- /dev/null +++ b/Malmo/samples/samples.iml @@ -0,0 +1,22 @@ + + + + + + + MIXIN + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Malmo/src/MissionSpec.cpp b/Malmo/src/MissionSpec.cpp index a274b42b7..8791244f5 100755 --- a/Malmo/src/MissionSpec.cpp +++ b/Malmo/src/MissionSpec.cpp @@ -382,8 +382,8 @@ namespace malmo child.erase("DiscreteMovementCommands"); child.erase("AbsoluteMovementCommands"); child.erase("SimpleCraftCommands"); - child.erase("NearbyCraftCommands"); - child.erase("NearbySmeltCommands"); + child.erase("SimpleCraftCraftCommands"); + child.erase("SimpleSmeltCommands"); child.erase("PlaceCommands"); child.erase("ChatCommands"); child.erase("MissionQuitCommands"); diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java b/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java index 65c076a2a..4c8b189d5 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Map.Entry; +import main.java.com.microsoft.Malmo.MissionHandlers.SimpleCraftNearbyCommandsImplementation; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; @@ -65,6 +66,8 @@ import com.microsoft.Malmo.MissionHandlers.ObservationFromGridImplementation; import com.microsoft.Malmo.MissionHandlers.ObservationFromSystemImplementation; import com.microsoft.Malmo.MissionHandlers.SimpleCraftCommandsImplementation; +import com.microsoft.Malmo.MissionHandlers.NearbyCraftCommandsImplementation; +import com.microsoft.Malmo.MissionHandlers.NearbySmeltCommandsImplementation; import com.microsoft.Malmo.Schemas.MissionInit; import com.microsoft.Malmo.Server.MalmoModServer; import com.microsoft.Malmo.Utils.AddressHelper; @@ -134,6 +137,8 @@ public void preInit(FMLPreInitializationEvent event) network.registerMessage(ObservationFromGridImplementation.GridRequestMessageHandler.class, ObservationFromGridImplementation.GridRequestMessage.class, 2, Side.SERVER); network.registerMessage(MalmoMessageHandler.class, MalmoMessage.class, 3, Side.CLIENT); // Malmo messages from server to client network.registerMessage(SimpleCraftCommandsImplementation.CraftMessageHandler.class, SimpleCraftCommandsImplementation.CraftMessage.class, 4, Side.SERVER); + network.registerMessage(NearbyCraftCommandsImplementation.CraftMessageHandler.class, NearbyCraftCommandsImplementation.CraftMessage.class, 4, Side.SERVER); + network.registerMessage(NearbySmeltCommandsImplementation.CraftMessageHandler.class, NearbySmeltCommandsImplementation.CraftMessage.class, 4, Side.SERVER); network.registerMessage(AbsoluteMovementCommandsImplementation.TeleportMessageHandler.class, AbsoluteMovementCommandsImplementation.TeleportMessage.class, 5, Side.SERVER); network.registerMessage(MalmoMessageHandler.class, MalmoMessage.class, 6, Side.SERVER); // Malmo messages from client to server network.registerMessage(InventoryCommandsImplementation.InventoryMessageHandler.class, InventoryCommandsImplementation.InventoryMessage.class, 7, Side.SERVER); diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java index b777b8d6b..00569f912 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java @@ -39,7 +39,7 @@ import com.microsoft.Malmo.MalmoMod; import com.microsoft.Malmo.Schemas.MissionInit; -import com.microsoft.Malmo.Schemas.SimpleCraftCommand; +import com.microsoft.Malmo.Schemas.NearbyCraftCommand; import com.microsoft.Malmo.Schemas.NearbyCraftCommands; import com.microsoft.Malmo.Utils.CraftingHelper; @@ -143,7 +143,7 @@ public IMessage onMessage(CraftMessage message, MessageContext ctx) { @Override protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { - if (verb.equalsIgnoreCase(SimpleCraftCommand.CRAFT.value())) { + if (verb.equalsIgnoreCase(NearbyCraftCommand.CRAFT.value())) { MalmoMod.network.sendToServer(new CraftMessage(parameter)); return true; } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java index 1c6aa2e0e..263617e53 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java @@ -38,8 +38,8 @@ import com.microsoft.Malmo.MalmoMod; import com.microsoft.Malmo.Schemas.MissionInit; -import com.microsoft.Malmo.Schemas.SimpleCraftCommand; -import com.microsoft.Malmo.Schemas.NearbyCraftCommands; +import com.microsoft.Malmo.Schemas.NearbySmeltCommand; +import com.microsoft.Malmo.Schemas.NearbySmeltCommands; import com.microsoft.Malmo.Utils.CraftingHelper; /** @@ -141,7 +141,7 @@ public IMessage onMessage(CraftMessage message, MessageContext ctx) { @Override protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { - if (verb.equalsIgnoreCase(SimpleCraftCommand.CRAFT.value())) { + if (verb.equalsIgnoreCase(NearbySmeltCommand.CRAFT.value())) { MalmoMod.network.sendToServer(new CraftMessage(parameter)); return true; } @@ -152,10 +152,10 @@ protected boolean onExecute(String verb, String parameter, MissionInit missionIn public boolean parseParameters(Object params) { furnaces = new ArrayList(); - if (!(params instanceof NearbyCraftCommands)) + if (!(params instanceof NearbySmeltCommands)) return false; - NearbyCraftCommands cParams = (NearbyCraftCommands) params; + NearbySmeltCommands cParams = (NearbySmeltCommands) params; setUpAllowAndDenyLists(cParams.getModifierList()); return true; } diff --git a/Minecraft/src/main/resources/schemas.index b/Minecraft/src/main/resources/schemas.index index 55dcedb71..70b4a99d8 100644 --- a/Minecraft/src/main/resources/schemas.index +++ b/Minecraft/src/main/resources/schemas.index @@ -1,5 +1,5 @@ +Mission.xsd +MissionEnded.xsd MissionHandlers.xsd MissionInit.xsd -MissionEnded.xsd Types.xsd -Mission.xsd diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd index 52d78a55a..666d596dd 100644 --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -1445,21 +1445,43 @@ A command for simple crafting: - Will look up all recipes that produce the requested object, and attempt each one in turn until one is successful or all have failed. This ignores all issues like requiring a crafting table / brewing stand etc, and the shape of the recipe (which items go in which slots on the crafting table). It will simply check to see whether the player has the necessary raw ingredients, and, if so, will remove them from the player's inventory and add the result of the recipe. + "{{{craft carpet PINK}}}" - For basic objects, use the ItemTypes or BlockTypes found in Types.xsd. Eg: + etc. + +
+ + + +
- "{{{craft diamond_pickaxe}}}" will remove three diamonds and two sticks from the player's inventory, and add a diamond pickaxe. + + + + A command for simple nearby crafting: - For more control over colours, types etc, add a Variation or Colour. Eg: + "{{{craftNearby carpet PINK}}}" - "{{{craft carpet PINK}}}" + etc. + + + + + + + + + + + A command for simple smelting: + + "{{{smeltNearby carpet PINK}}}" etc. - + @@ -1546,7 +1568,7 @@ - + @@ -1721,7 +1743,7 @@ - + @@ -1751,7 +1773,7 @@ - + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index c3359a536..28b767452 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -1462,6 +1462,37 @@ + + + + + + A command for simple nearby crafting: + + "{{{craftNearby carpet PINK}}}" + + etc. + + + + + + + + + + + A command for simple smelting: + + "{{{smelt carpet PINK}}}" + + etc. + + + + + + @@ -1721,7 +1752,7 @@ - + @@ -1730,16 +1761,16 @@
- + When present, the Mod will accept simple commands that implement a basic form of smelting. Success of the smelt command depends on the presence of a nearby furnace previously placed by the agent and within reach and in field of view. Fails when a command corresponds to an item not able to be smelted. Each command takes fuel as if the agent had placed the items in a furnace. - + Eg: - + If called on 16 iron ore, requires 2 coal, 2 charcoal, 11 planks, etc. - + If called twice separately on 8 iron ore, requires 1 coal and then 1 coal, etc. @@ -1751,7 +1782,7 @@ - + @@ -1760,7 +1791,7 @@ - + diff --git a/Schemas/Schemas.iml b/Schemas/Schemas.iml new file mode 100644 index 000000000..8021953ed --- /dev/null +++ b/Schemas/Schemas.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file From f8150354ebb25ae4ff7a19bd9ee75d86d6509cf7 Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Thu, 21 Feb 2019 22:20:37 -0500 Subject: [PATCH 16/40] Merged master into craft edits --- .gitignore | 1 + ...entQuitFromCraftingItemImplementation.java | 146 ++++++++++++++++ .../RewardForCraftingItemImplementation.java | 158 ++++++++++++++++++ Schemas/MissionHandlers.xsd | 74 +++++--- Schemas/MissionHandlers.xsd.in | 71 ++++++-- 5 files changed, 413 insertions(+), 37 deletions(-) create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java mode change 100755 => 100644 Schemas/MissionHandlers.xsd diff --git a/.gitignore b/.gitignore index c36968006..14818ce5f 100755 --- a/.gitignore +++ b/.gitignore @@ -167,6 +167,7 @@ ClientBin/ *.pfx *.publishsettings node_modules/ +.DS_Store # RIA/Silverlight projects Generated_Code/ diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java new file mode 100644 index 000000000..878cb3de9 --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java @@ -0,0 +1,146 @@ +package com.microsoft.Malmo.MissionHandlers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; + +import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; +import com.microsoft.Malmo.MissionHandlers.RewardForItemBase.ItemMatcher; +import com.microsoft.Malmo.Schemas.AgentQuitFromCraftingItem; +import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithDescription; +import com.microsoft.Malmo.Schemas.MissionInit; + +/** + * + * @author Cayden Codel, Carnegie Mellon University + * + * Gives agents rewards when items are crafted. + * + */ +public class AgentQuitFromCraftingItemImplementation extends HandlerBase implements IWantToQuit { + + private AgentQuitFromCraftingItem params; + private HashMap craftedItems; + private List matchers; + private String quitCode = ""; + boolean wantToQuit = false; + boolean callCraft = true; + + public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { + String description; + + ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { + super(spec); + this.description = spec.getDescription(); + } + + String description() { + return this.description; + } + } + + @Override + public boolean parseParameters(Object params) { + if (params == null || !(params instanceof AgentQuitFromCraftingItem)) + return false; + + this.params = (AgentQuitFromCraftingItem) params; + this.matchers = new ArrayList(); + for (BlockOrItemSpecWithDescription bs : this.params.getItem()) + this.matchers.add(new ItemQuitMatcher(bs)); + return true; + } + + @Override + public boolean doIWantToQuit(MissionInit missionInit) { + return this.wantToQuit; + } + + @Override + public String getOutcome() { + return this.quitCode; + } + + @Override + public void prepare(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.register(this); + craftedItems = new HashMap(); + } + + @Override + public void cleanup() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { + if (callCraft) + checkForMatch(event.crafting); + + callCraft = !callCraft; + } + + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); + else + return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName()); + + } + + private void addCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getUnlocalizedName())); + craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + } else { + int prev = (craftedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName())); + craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + } + + private void checkForMatch(ItemStack is) { + int savedCrafted = getCraftedItemCount(is); + if (is != null && is.getItem() != null) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedCrafted != 0) { + if (is.getCount() + savedCrafted >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } + } + + addCraftedItemCount(is); + } + } +} diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java new file mode 100644 index 000000000..522bd6752 --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java @@ -0,0 +1,158 @@ +package com.microsoft.Malmo.MissionHandlers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import com.microsoft.Malmo.MalmoMod; +import com.microsoft.Malmo.MalmoMod.IMalmoMessageListener; +import com.microsoft.Malmo.MalmoMod.MalmoMessageType; +import com.microsoft.Malmo.MissionHandlerInterfaces.IRewardProducer; +import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithReward; +import com.microsoft.Malmo.Schemas.MissionInit; +import com.microsoft.Malmo.Schemas.RewardForCraftingItem; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; + +/** + * + * @author Cayden Codel, Carnegie Mellon University + * + * Sends a reward when the agent crafts the specified item with + * specified amounts. + */ +public class RewardForCraftingItemImplementation extends RewardForItemBase + implements IRewardProducer, IMalmoMessageListener { + + private RewardForCraftingItem params; + private ArrayList matchers; + private HashMap craftedItems; + boolean callCraft = true; + + @SubscribeEvent + public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { + if (callCraft) + checkForMatch(event.crafting); + + callCraft = !callCraft; + } + + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); + else + return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName()); + + } + + private void addCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getUnlocalizedName())); + craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + } else { + int prev = (craftedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName())); + craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + } + + private void checkForMatch(ItemStack is) { + int savedCrafted = getCraftedItemCount(is); + if (is != null && is.getItem() != null) { + for (ItemMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (!params.isSparse()) { + if (savedCrafted != 0 && savedCrafted < matcher.matchSpec.getAmount()) { + for (int i = savedCrafted; i < matcher.matchSpec.getAmount() + && i - savedCrafted < is.getCount(); i++) + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + + } else if (savedCrafted != 0 && savedCrafted >= matcher.matchSpec.getAmount()) { + // Do nothing + } else { + for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + + } + } else { + if (savedCrafted < matcher.matchSpec.getAmount() + && savedCrafted + is.getCount() >= matcher.matchSpec.getAmount()) + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } + + addCraftedItemCount(is); + } + + } + + @Override + public boolean parseParameters(Object params) { + if (params == null || !(params instanceof RewardForCraftingItem)) + return false; + + matchers = new ArrayList(); + + this.params = (RewardForCraftingItem) params; + for (BlockOrItemSpecWithReward spec : this.params.getItem()) + this.matchers.add(new ItemMatcher(spec)); + + return true; + } + + @Override + public void prepare(MissionInit missionInit) { + super.prepare(missionInit); + MinecraftForge.EVENT_BUS.register(this); + MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + craftedItems = new HashMap(); + } + + @Override + public void getReward(MissionInit missionInit, MultidimensionalReward reward) { + super.getReward(missionInit, reward); + } + + @Override + public void cleanup() { + super.cleanup(); + MinecraftForge.EVENT_BUS.unregister(this); + MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + } + + @Override + public void onMessage(MalmoMessageType messageType, Map data) { + } +} diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd old mode 100755 new mode 100644 index 14593c411..09854c2cb --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -139,28 +139,28 @@ - + - Loads a saved world from disk. You can find the saved worlds in "{{{Minecraft\run\saves}}}". Use the full path to one of those folders. - - If Minecraft is running on a different machine then copy the folder to a readable network location and update the path accordingly. Example: - - {{{<FileWorldGenerator src="\\\\machine-id\\shared\\ProjectMalmo\\saved_maps\\arena" />}}} + Generates a survival world with the specified biome. - + - The path to the saved world folder. + The biome type for the world. Each chunk will be loaded with the biome specified. + + If left blank, the world will be a normal survival world. + + Biome ID #'s can be found here: https://minecraft.gamepedia.com/Biome#Biome_IDs - Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested source filename). + Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested seed). Force reloading is slow, but will guarantee that no world changes will carry over between missions. @@ -176,28 +176,28 @@ - + - Generates a survival world with the specified biome. + Loads a saved world from disk. You can find the saved worlds in "{{{Minecraft\run\saves}}}". Use the full path to one of those folders. + + If Minecraft is running on a different machine then copy the folder to a readable network location and update the path accordingly. Example: + + {{{<FileWorldGenerator src="\\\\machine-id\\shared\\ProjectMalmo\\saved_maps\\arena" />}}} - + - The biome type for the world. Each chunk will be loaded with the biome specified. - - If left blank, the world will be a normal survival world. - - Biome ID #'s can be found here: https://minecraft.gamepedia.com/Biome#Biome_IDs + The path to the saved world folder. - Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested seed). + Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested source filename). Force reloading is slow, but will guarantee that no world changes will carry over between missions. @@ -1066,7 +1066,9 @@ Sets whether or not the compass location should be randomized within a certain radius. + If false, will set the compass location to the block that was randomly placed. + If true, will set the compass location to a random spot within the radius specified below. @@ -1670,6 +1672,7 @@ + @@ -2053,7 +2056,6 @@ - @@ -2152,12 +2154,14 @@ + + @@ -2259,6 +2263,25 @@ + + + + Sends a reward when the agent crafts a specific item. + + If Sparse is set to true, will only give full reward on crafting of entire amount. + + Otherwise, will give the reward amount notated for each item crafted up to the amount noted. + + + + + + + + + + + @@ -2551,6 +2574,19 @@ + + + + When this is included the agent's mission will end when they craft a specified item. + + + + + + + + + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index af106e8be..832006661 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -139,28 +139,28 @@ - + - Loads a saved world from disk. You can find the saved worlds in "{{{Minecraft\run\saves}}}". Use the full path to one of those folders. - - If Minecraft is running on a different machine then copy the folder to a readable network location and update the path accordingly. Example: - - {{{<FileWorldGenerator src="\\\\machine-id\\shared\\ProjectMalmo\\saved_maps\\arena" />}}} + Generates a survival world with the specified biome. - + - The path to the saved world folder. + The biome type for the world. Each chunk will be loaded with the biome specified. + + If left blank, the world will be a normal survival world. + + Biome ID #'s can be found here: https://minecraft.gamepedia.com/Biome#Biome_IDs - Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested source filename). + Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested seed). Force reloading is slow, but will guarantee that no world changes will carry over between missions. @@ -176,28 +176,28 @@ - + - Generates a survival world with the specified biome. + Loads a saved world from disk. You can find the saved worlds in "{{{Minecraft\run\saves}}}". Use the full path to one of those folders. + + If Minecraft is running on a different machine then copy the folder to a readable network location and update the path accordingly. Example: + + {{{<FileWorldGenerator src="\\\\machine-id\\shared\\ProjectMalmo\\saved_maps\\arena" />}}} - + - The biome type for the world. Each chunk will be loaded with the biome specified. - - If left blank, the world will be a normal survival world. - - Biome ID #'s can be found here: https://minecraft.gamepedia.com/Biome#Biome_IDs + The path to the saved world folder. - Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested seed). + Set this to true to force the world to be reloaded, otherwise the current world will be used (provided it matches the requested source filename). Force reloading is slow, but will guarantee that no world changes will carry over between missions. @@ -1670,6 +1670,7 @@ + @@ -2152,12 +2153,14 @@ + + @@ -2259,6 +2262,25 @@ + + + + Sends a reward when the agent crafts a specific item. + + If Sparse is set to true, will only give full reward on crafting of entire amount. + + Otherwise, will give the reward amount notated for each item crafted up to the amount noted. + + + + + + + + + + + @@ -2551,6 +2573,19 @@ + + + + When this is included the agent's mission will end when they craft a specified item. + + + + + + + + + From 60e4ea626c4a27f17d585b68729391ab9f2bd4b9 Mon Sep 17 00:00:00 2001 From: ccodel Date: Thu, 6 Dec 2018 16:29:57 -0500 Subject: [PATCH 17/40] Reimplemented craft, collect handlers, added possess handler with decrement --- ...tQuitFromCollectingItemImplementation.java | 229 +++++++++++------- ...tQuitFromPossessingItemImplementation.java | 179 ++++++++++++++ .../RewardForCraftingItemImplementation.java | 19 +- Schemas/Mission.xsd | 3 + Schemas/Mission.xsd.in | 3 + Schemas/MissionHandlers.xsd | 13 + Schemas/MissionHandlers.xsd.in | 13 + 7 files changed, 366 insertions(+), 93 deletions(-) create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java mode change 100755 => 100644 Schemas/Mission.xsd diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java index 42b37c887..0300760c7 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java @@ -1,107 +1,156 @@ package com.microsoft.Malmo.MissionHandlers; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import net.minecraft.item.ItemStack; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.EntityItemPickupEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; +import com.microsoft.Malmo.MissionHandlers.AgentQuitFromCraftingItemImplementation.ItemQuitMatcher; import com.microsoft.Malmo.MissionHandlers.RewardForCollectingItemImplementation.GainItemEvent; +import com.microsoft.Malmo.MissionHandlers.RewardForItemBase.ItemMatcher; import com.microsoft.Malmo.Schemas.AgentQuitFromCollectingItem; import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithDescription; import com.microsoft.Malmo.Schemas.MissionInit; -public class AgentQuitFromCollectingItemImplementation extends HandlerBase implements IWantToQuit -{ - AgentQuitFromCollectingItem params; - List matchers; - String quitCode = ""; - boolean wantToQuit = false; - - public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher - { - String description; - - ItemQuitMatcher(BlockOrItemSpecWithDescription spec) - { - super(spec); - this.description = spec.getDescription(); - } - - String description() - { - return this.description; - } - } - - @Override - public boolean parseParameters(Object params) - { - if (params == null || !(params instanceof AgentQuitFromCollectingItem)) - return false; - - this.params = (AgentQuitFromCollectingItem)params; - this.matchers = new ArrayList(); - for (BlockOrItemSpecWithDescription bs : this.params.getItem()) - this.matchers.add(new ItemQuitMatcher(bs)); - return true; - } - - @Override - public boolean doIWantToQuit(MissionInit missionInit) - { - return this.wantToQuit; - } - - @Override - public String getOutcome() - { - return this.quitCode; - } - - @Override - public void prepare(MissionInit missionInit) - { - MinecraftForge.EVENT_BUS.register(this); - } - - @Override - public void cleanup() - { - MinecraftForge.EVENT_BUS.unregister(this); - } - - @SubscribeEvent - public void onGainItem(GainItemEvent event) - { - checkForMatch(event.stack); - } - - @SubscribeEvent - public void onPickupItem(EntityItemPickupEvent event) - { - if (event.getItem() != null && event.getItem().getEntityItem() != null) - { - ItemStack stack = event.getItem().getEntityItem(); - checkForMatch(stack); - } - } - - private void checkForMatch(ItemStack is) - { - if (is != null) - { - for (ItemQuitMatcher matcher : this.matchers) - { - if (matcher.matches(is)) - { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } - } - } +public class AgentQuitFromCollectingItemImplementation extends HandlerBase implements IWantToQuit { + AgentQuitFromCollectingItem params; + private HashMap collectedItems; + List matchers; + String quitCode = ""; + boolean wantToQuit = false; + boolean callCraft = true; + + public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { + String description; + + ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { + super(spec); + this.description = spec.getDescription(); + } + + String description() { + return this.description; + } + } + + @Override + public boolean parseParameters(Object params) { + if (params == null || !(params instanceof AgentQuitFromCollectingItem)) + return false; + + this.params = (AgentQuitFromCollectingItem) params; + this.matchers = new ArrayList(); + for (BlockOrItemSpecWithDescription bs : this.params.getItem()) + this.matchers.add(new ItemQuitMatcher(bs)); + return true; + } + + @Override + public boolean doIWantToQuit(MissionInit missionInit) { + return this.wantToQuit; + } + + @Override + public String getOutcome() { + return this.quitCode; + } + + @Override + public void prepare(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.register(this); + collectedItems = new HashMap(); + } + + @Override + public void cleanup() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void onGainItem(GainItemEvent event) { + System.out.println("Gained an item: " + event.stack.getUnlocalizedName()); + checkForMatch(event.stack); + } + + @SubscribeEvent + public void onPickupItem(EntityItemPickupEvent event) { + if (event.getItem() != null && event.getItem().getEntityItem() != null) { + ItemStack stack = event.getItem().getEntityItem(); + checkForMatch(stack); + } + } + + @SubscribeEvent + public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { + if (callCraft) + checkForMatch(event.crafting); + + callCraft = !callCraft; + } + + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getUnlocalizedName()); + else + return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName()); + + } + + private void addCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + } else { + int prev = (collectedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName())); + collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + } + + private void checkForMatch(ItemStack is) { + int savedCrafted = getCraftedItemCount(is); + if (is != null && is.getItem() != null) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedCrafted != 0) { + if (is.getCount() + savedCrafted >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } + } + + addCollectedItemCount(is); + } + } } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java new file mode 100644 index 000000000..380e2f928 --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java @@ -0,0 +1,179 @@ +package com.microsoft.Malmo.MissionHandlers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.player.EntityItemPickupEvent; +import net.minecraftforge.event.entity.item.ItemTossEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; +import com.microsoft.Malmo.MissionHandlers.AgentQuitFromCraftingItemImplementation.ItemQuitMatcher; +import com.microsoft.Malmo.MissionHandlers.RewardForCollectingItemImplementation.GainItemEvent; +import com.microsoft.Malmo.MissionHandlers.RewardForItemBase.ItemMatcher; +import com.microsoft.Malmo.Schemas.AgentQuitFromPossessingItem; +import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithDescription; +import com.microsoft.Malmo.Schemas.MissionInit; + +public class AgentQuitFromPossessingItemImplementation extends HandlerBase implements IWantToQuit { + AgentQuitFromPossessingItem params; + private HashMap collectedItems; + List matchers; + String quitCode = ""; + boolean wantToQuit = false; + boolean callCraft = true; + + public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { + String description; + + ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { + super(spec); + this.description = spec.getDescription(); + } + + String description() { + return this.description; + } + } + + @Override + public boolean parseParameters(Object params) { + if (params == null || !(params instanceof AgentQuitFromPossessingItem)) + return false; + + this.params = (AgentQuitFromPossessingItem) params; + this.matchers = new ArrayList(); + for (BlockOrItemSpecWithDescription bs : this.params.getItem()) + this.matchers.add(new ItemQuitMatcher(bs)); + return true; + } + + @Override + public boolean doIWantToQuit(MissionInit missionInit) { + return this.wantToQuit; + } + + @Override + public String getOutcome() { + return this.quitCode; + } + + @Override + public void prepare(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.register(this); + collectedItems = new HashMap(); + } + + @Override + public void cleanup() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void onGainItem(GainItemEvent event) { + System.out.println("Gained an item: " + event.stack.getUnlocalizedName()); + checkForMatch(event.stack); + } + + @SubscribeEvent + public void onPickupItem(EntityItemPickupEvent event) { + if (event.getItem() != null && event.getItem().getEntityItem() != null) { + ItemStack stack = event.getItem().getEntityItem(); + checkForMatch(stack); + } + } + + @SubscribeEvent + public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { + if (callCraft) + checkForMatch(event.crafting); + + callCraft = !callCraft; + } + + @SubscribeEvent + public void onItemToss(ItemTossEvent event) { + if (event.getEntityItem() != null && event.getEntityItem().getEntityItem() != null) { + ItemStack stack = event.getEntityItem().getEntityItem(); + removeCollectedItem(stack); + } + } + + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getUnlocalizedName()); + else + return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName()); + + } + + private void addCollectedItem(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + } else { + int prev = (collectedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName())); + collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + } + + private void removeCollectedItem(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + collectedItems.put(is.getUnlocalizedName(), Integer.max(0, prev - is.getCount())); + } else { + int prev = (collectedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName())); + collectedItems.put(is.getItem().getUnlocalizedName(), Integer.max(0, prev - is.getCount())); + } + } + + private void checkForMatch(ItemStack is) { + int savedCrafted = getCraftedItemCount(is); + if (is != null && is.getItem() != null) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedCrafted != 0) { + if (is.getCount() + savedCrafted >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } + } + + addCollectedItem(is); + } + } +} diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java index 522bd6752..8329fddd6 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java @@ -79,36 +79,49 @@ private void addCraftedItemCount(ItemStack is) { } private void checkForMatch(ItemStack is) { + //System.out.println("Checking for match on " + is.getItem().getUnlocalizedName()); int savedCrafted = getCraftedItemCount(is); + //System.out.println("Previous saved amount is " + savedCrafted); if (is != null && is.getItem() != null) { for (ItemMatcher matcher : this.matchers) { if (matcher.matches(is)) { if (!params.isSparse()) { if (savedCrafted != 0 && savedCrafted < matcher.matchSpec.getAmount()) { for (int i = savedCrafted; i < matcher.matchSpec.getAmount() - && i - savedCrafted < is.getCount(); i++) + && i - savedCrafted < is.getCount(); i++) { + //System.out.println("Sparse, had nonzero saved crafted amount, giving a reward of " + // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); this.adjustAndDistributeReward( ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), params.getDimension(), ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } } else if (savedCrafted != 0 && savedCrafted >= matcher.matchSpec.getAmount()) { // Do nothing + //System.out + // .println("Sparse, had nonzero saved crafted amount, but not enough new for reward"); } else { - for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) + for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { + //System.out.println("Had zero saved crafted amount, giving a reward of " + // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); this.adjustAndDistributeReward( ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), params.getDimension(), ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } } } else { if (savedCrafted < matcher.matchSpec.getAmount() - && savedCrafted + is.getCount() >= matcher.matchSpec.getAmount()) + && savedCrafted + is.getCount() >= matcher.matchSpec.getAmount()) { + //System.out.println("Not sparse, giving a reward of " + // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); this.adjustAndDistributeReward( ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), params.getDimension(), ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } } } } diff --git a/Schemas/Mission.xsd b/Schemas/Mission.xsd old mode 100755 new mode 100644 index 12261c8e0..5dcf28f85 --- a/Schemas/Mission.xsd +++ b/Schemas/Mission.xsd @@ -353,6 +353,7 @@ + @@ -378,6 +379,8 @@ + + diff --git a/Schemas/Mission.xsd.in b/Schemas/Mission.xsd.in index c04f7b6f0..a88e6f104 100644 --- a/Schemas/Mission.xsd.in +++ b/Schemas/Mission.xsd.in @@ -353,6 +353,7 @@ + @@ -378,6 +379,8 @@ + + diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd index 09854c2cb..af8c46bcd 100644 --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -2586,6 +2586,19 @@ + + + + + When this is included the agent's mission will end when they possess the specified item in their inventory all at once. + + + + + + + + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index 832006661..df8c3d097 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -2585,6 +2585,19 @@ + + + + + When this is included the agent's mission will end when they possess the specified item in their inventory all at once. + + + + + + + + From f5776ac6e986242f0fd774ee554c1ccf55a8921c Mon Sep 17 00:00:00 2001 From: ccodel Date: Tue, 5 Feb 2019 21:39:17 -0500 Subject: [PATCH 18/40] Added smelting reward and quit handlers --- ...entQuitFromSmeltingItemImplementation.java | 146 +++++++++++++++ .../RewardForSmeltingItemImplementation.java | 171 ++++++++++++++++++ Schemas/Mission.xsd | 2 + Schemas/Mission.xsd.in | 2 + Schemas/MissionEnded.xsd | 0 Schemas/MissionHandlers.xsd | 32 ++++ Schemas/MissionHandlers.xsd.in | 32 ++++ Schemas/MissionInit.xsd | 0 Schemas/Types.xsd | 0 9 files changed, 385 insertions(+) create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java mode change 100755 => 100644 Schemas/MissionEnded.xsd mode change 100755 => 100644 Schemas/MissionInit.xsd mode change 100755 => 100644 Schemas/Types.xsd diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java new file mode 100644 index 000000000..9ebc9caf6 --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java @@ -0,0 +1,146 @@ +package com.microsoft.Malmo.MissionHandlers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; + +import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; +import com.microsoft.Malmo.MissionHandlers.RewardForItemBase.ItemMatcher; +import com.microsoft.Malmo.Schemas.AgentQuitFromSmeltingItem; +import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithDescription; +import com.microsoft.Malmo.Schemas.MissionInit; + +/** + * + * @author Cayden Codel, Carnegie Mellon University + * + * Gives agents rewards when items are smelted. + * + */ +public class AgentQuitFromSmeltingItemImplementation extends HandlerBase implements IWantToQuit { + + private AgentQuitFromSmeltingItem params; + private HashMap smeltedItems; + private List matchers; + private String quitCode = ""; + boolean wantToQuit = false; + boolean callSmelt = true; + + public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { + String description; + + ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { + super(spec); + this.description = spec.getDescription(); + } + + String description() { + return this.description; + } + } + + @Override + public boolean parseParameters(Object params) { + if (params == null || !(params instanceof AgentQuitFromSmeltingItem)) + return false; + + this.params = (AgentQuitFromSmeltingItem) params; + this.matchers = new ArrayList(); + for (BlockOrItemSpecWithDescription bs : this.params.getItem()) + this.matchers.add(new ItemQuitMatcher(bs)); + return true; + } + + @Override + public boolean doIWantToQuit(MissionInit missionInit) { + return this.wantToQuit; + } + + @Override + public String getOutcome() { + return this.quitCode; + } + + @Override + public void prepare(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.register(this); + smeltedItems = new HashMap(); + } + + @Override + public void cleanup() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { + if (callSmelt) + checkForMatch(event.smelting); + + callSmelt = !callSmelt; + } + + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getSmeltedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (smeltedItems.get(is.getUnlocalizedName()) == null) ? 0 : smeltedItems.get(is.getUnlocalizedName()); + else + return (smeltedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : smeltedItems.get(is.getItem().getUnlocalizedName()); + + } + + private void addSmeltedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (smeltedItems.get(is.getUnlocalizedName()) == null ? 0 + : smeltedItems.get(is.getUnlocalizedName())); + smeltedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + } else { + int prev = (smeltedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : smeltedItems.get(is.getItem().getUnlocalizedName())); + smeltedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + } + + private void checkForMatch(ItemStack is) { + int savedSmelted = getSmeltedItemCount(is); + if (is != null && is.getItem() != null) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedSmelted != 0) { + if (is.getCount() + savedSmelted >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } + } + + addSmeltedItemCount(is); + } + } +} diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java new file mode 100644 index 000000000..ee4a5fded --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java @@ -0,0 +1,171 @@ +package com.microsoft.Malmo.MissionHandlers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import com.microsoft.Malmo.MalmoMod; +import com.microsoft.Malmo.MalmoMod.IMalmoMessageListener; +import com.microsoft.Malmo.MalmoMod.MalmoMessageType; +import com.microsoft.Malmo.MissionHandlerInterfaces.IRewardProducer; +import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithReward; +import com.microsoft.Malmo.Schemas.MissionInit; +import com.microsoft.Malmo.Schemas.RewardForSmeltingItem; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; + +/** + * + * @author Cayden Codel, Carnegie Mellon University + * + * Sends a reward when the agent smelts the specified item with + * specified amounts. + */ +public class RewardForSmeltingItemImplementation extends RewardForItemBase + implements IRewardProducer, IMalmoMessageListener { + + private RewardForSmeltingItem params; + private ArrayList matchers; + private HashMap smeltedItems; + boolean callSmelt = true; + + @SubscribeEvent + public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { + if (callSmelt) + checkForMatch(event.smelting); + + callSmelt = !callSmelt; + } + + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (smeltedItems.get(is.getUnlocalizedName()) == null) ? 0 : smeltedItems.get(is.getUnlocalizedName()); + else + return (smeltedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : smeltedItems.get(is.getItem().getUnlocalizedName()); + + } + + private void addSmeltedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (smeltedItems.get(is.getUnlocalizedName()) == null ? 0 + : smeltedItems.get(is.getUnlocalizedName())); + smeltedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + } else { + int prev = (smeltedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : smeltedItems.get(is.getItem().getUnlocalizedName())); + smeltedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + } + + private void checkForMatch(ItemStack is) { + //System.out.println("Checking for match on " + is.getItem().getUnlocalizedName()); + int savedCrafted = getCraftedItemCount(is); + //System.out.println("Previous saved amount is " + savedCrafted); + if (is != null && is.getItem() != null) { + for (ItemMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (!params.isSparse()) { + if (savedCrafted != 0 && savedCrafted < matcher.matchSpec.getAmount()) { + for (int i = savedCrafted; i < matcher.matchSpec.getAmount() + && i - savedCrafted < is.getCount(); i++) { + //System.out.println("Sparse, had nonzero saved crafted amount, giving a reward of " + // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + + } else if (savedCrafted != 0 && savedCrafted >= matcher.matchSpec.getAmount()) { + // Do nothing + //System.out + // .println("Sparse, had nonzero saved crafted amount, but not enough new for reward"); + } else { + for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { + //System.out.println("Had zero saved crafted amount, giving a reward of " + // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + + } + } else { + if (savedCrafted < matcher.matchSpec.getAmount() + && savedCrafted + is.getCount() >= matcher.matchSpec.getAmount()) { + //System.out.println("Not sparse, giving a reward of " + // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } + } + + addSmeltedItemCount(is); + } + + } + + @Override + public boolean parseParameters(Object params) { + if (params == null || !(params instanceof RewardForSmeltingItem)) + return false; + + matchers = new ArrayList(); + + this.params = (RewardForSmeltingItem) params; + for (BlockOrItemSpecWithReward spec : this.params.getItem()) + this.matchers.add(new ItemMatcher(spec)); + + return true; + } + + @Override + public void prepare(MissionInit missionInit) { + super.prepare(missionInit); + MinecraftForge.EVENT_BUS.register(this); + MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + smeltedItems = new HashMap(); + } + + @Override + public void getReward(MissionInit missionInit, MultidimensionalReward reward) { + super.getReward(missionInit, reward); + } + + @Override + public void cleanup() { + super.cleanup(); + MinecraftForge.EVENT_BUS.unregister(this); + MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + } + + @Override + public void onMessage(MalmoMessageType messageType, Map data) { + } +} diff --git a/Schemas/Mission.xsd b/Schemas/Mission.xsd index 5dcf28f85..8b6a1e8aa 100644 --- a/Schemas/Mission.xsd +++ b/Schemas/Mission.xsd @@ -354,6 +354,7 @@ + @@ -380,6 +381,7 @@ + diff --git a/Schemas/Mission.xsd.in b/Schemas/Mission.xsd.in index a88e6f104..bc8a8e3cc 100644 --- a/Schemas/Mission.xsd.in +++ b/Schemas/Mission.xsd.in @@ -354,6 +354,7 @@ + @@ -380,6 +381,7 @@ + diff --git a/Schemas/MissionEnded.xsd b/Schemas/MissionEnded.xsd old mode 100755 new mode 100644 diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd index af8c46bcd..32a8064cb 100644 --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -2281,6 +2281,25 @@ + + + + + Sends a reward when the agent smelts a specific item. + + If Sparse is set to true, will only give full reward on crafting of entire amount. + + Otherwise, will give the reward amount notated for each item crafted up to the amount noted. + + + + + + + + + + @@ -2587,6 +2606,19 @@ + + + + When this is included the agent's mission will end when they smelt a specified item. + + + + + + + + + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index df8c3d097..cc303a351 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -2280,6 +2280,25 @@ + + + + + Sends a reward when the agent smelts a specific item. + + If Sparse is set to true, will only give full reward on crafting of entire amount. + + Otherwise, will give the reward amount notated for each item crafted up to the amount noted. + + + + + + + + + + @@ -2586,6 +2605,19 @@ + + + + When this is included the agent's mission will end when they smelt a specified item. + + + + + + + + + diff --git a/Schemas/MissionInit.xsd b/Schemas/MissionInit.xsd old mode 100755 new mode 100644 diff --git a/Schemas/Types.xsd b/Schemas/Types.xsd old mode 100755 new mode 100644 From 2797851aa894b8c2754e310c8ed3fb3059b57561 Mon Sep 17 00:00:00 2001 From: ccodel Date: Fri, 8 Feb 2019 22:25:08 -0500 Subject: [PATCH 19/40] Bulk of implementation done, onto testing --- ...tQuitFromCollectingItemImplementation.java | 270 ++++++++-------- ...entQuitFromCraftingItemImplementation.java | 35 +-- ...tQuitFromPossessingItemImplementation.java | 125 ++++---- ...entQuitFromSmeltingItemImplementation.java | 252 +++++++-------- ...RewardForCollectingItemImplementation.java | 226 +++++++++----- .../RewardForCraftingItemImplementation.java | 287 +++++++++--------- ...RewardForPossessingItemImplementation.java | 232 ++++++++++++++ .../RewardForSmeltingItemImplementation.java | 79 +++-- Schemas/Mission.xsd | 3 +- Schemas/Mission.xsd.in | 3 +- Schemas/MissionHandlers.xsd | 28 +- Schemas/MissionHandlers.xsd.in | 28 +- 12 files changed, 955 insertions(+), 613 deletions(-) create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForPossessingItemImplementation.java diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java index 0300760c7..ab8f95b4e 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCollectingItemImplementation.java @@ -7,150 +7,144 @@ import net.minecraft.item.ItemStack; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.EntityItemPickupEvent; -import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; -import com.microsoft.Malmo.MissionHandlers.AgentQuitFromCraftingItemImplementation.ItemQuitMatcher; import com.microsoft.Malmo.MissionHandlers.RewardForCollectingItemImplementation.GainItemEvent; -import com.microsoft.Malmo.MissionHandlers.RewardForItemBase.ItemMatcher; import com.microsoft.Malmo.Schemas.AgentQuitFromCollectingItem; import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithDescription; import com.microsoft.Malmo.Schemas.MissionInit; +/** + * Quits the mission when the agent has collected the right amount of items. The count on the item collection is absolute. + */ public class AgentQuitFromCollectingItemImplementation extends HandlerBase implements IWantToQuit { - AgentQuitFromCollectingItem params; - private HashMap collectedItems; - List matchers; - String quitCode = ""; - boolean wantToQuit = false; - boolean callCraft = true; - - public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { - String description; - - ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { - super(spec); - this.description = spec.getDescription(); - } - - String description() { - return this.description; - } - } - - @Override - public boolean parseParameters(Object params) { - if (params == null || !(params instanceof AgentQuitFromCollectingItem)) - return false; - - this.params = (AgentQuitFromCollectingItem) params; - this.matchers = new ArrayList(); - for (BlockOrItemSpecWithDescription bs : this.params.getItem()) - this.matchers.add(new ItemQuitMatcher(bs)); - return true; - } - - @Override - public boolean doIWantToQuit(MissionInit missionInit) { - return this.wantToQuit; - } - - @Override - public String getOutcome() { - return this.quitCode; - } - - @Override - public void prepare(MissionInit missionInit) { - MinecraftForge.EVENT_BUS.register(this); - collectedItems = new HashMap(); - } - - @Override - public void cleanup() { - MinecraftForge.EVENT_BUS.unregister(this); - } - - @SubscribeEvent - public void onGainItem(GainItemEvent event) { - System.out.println("Gained an item: " + event.stack.getUnlocalizedName()); - checkForMatch(event.stack); - } - - @SubscribeEvent - public void onPickupItem(EntityItemPickupEvent event) { - if (event.getItem() != null && event.getItem().getEntityItem() != null) { - ItemStack stack = event.getItem().getEntityItem(); - checkForMatch(stack); - } - } - - @SubscribeEvent - public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { - if (callCraft) - checkForMatch(event.crafting); - - callCraft = !callCraft; - } - - private boolean getVariant(ItemStack is) { - for (ItemMatcher matcher : matchers) { - if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { - if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) - return true; - if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) - return true; - } - } - - return false; - } - - private int getCraftedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) - return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 - : collectedItems.get(is.getUnlocalizedName()); - else - return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 - : collectedItems.get(is.getItem().getUnlocalizedName()); - - } - - private void addCollectedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) { - int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getUnlocalizedName())); - collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - } else { - int prev = (collectedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getItem().getUnlocalizedName())); - collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - } - } - - private void checkForMatch(ItemStack is) { - int savedCrafted = getCraftedItemCount(is); - if (is != null && is.getItem() != null) { - for (ItemQuitMatcher matcher : this.matchers) { - if (matcher.matches(is)) { - if (savedCrafted != 0) { - if (is.getCount() + savedCrafted >= matcher.matchSpec.getAmount()) { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } else if (is.getCount() >= matcher.matchSpec.getAmount()) { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } - } - - addCollectedItemCount(is); - } - } -} + + private AgentQuitFromCollectingItem params; + private HashMap collectedItems; + private List matchers; + private String quitCode = ""; + private boolean wantToQuit = false; + + public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { + String description; + + ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { + super(spec); + this.description = spec.getDescription(); + } + + String description() { + return this.description; + } + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof AgentQuitFromCollectingItem)) + return false; + + this.params = (AgentQuitFromCollectingItem) params; + this.matchers = new ArrayList(); + for (BlockOrItemSpecWithDescription bs : this.params.getItem()) + this.matchers.add(new ItemQuitMatcher(bs)); + return true; + } + + @Override + public boolean doIWantToQuit(MissionInit missionInit) { + return this.wantToQuit; + } + + @Override + public String getOutcome() { + return this.quitCode; + } + + @Override + public void prepare(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.register(this); + collectedItems = new HashMap(); + } + + @Override + public void cleanup() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void onGainItem(GainItemEvent event) { + checkForMatch(event.stack); + } + + @SubscribeEvent + public void onPickupItem(EntityItemPickupEvent event) { + if (event.getItem() != null) { + ItemStack stack = event.getItem().getEntityItem(); + checkForMatch(stack); + } + } + + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ + private boolean getVariant(ItemStack is) { + for (ItemQuitMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private void addCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + if (variant) + collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + else + collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + + private int getCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 : collectedItems.get(is.getUnlocalizedName()); + else + return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName()); + } + + private void checkForMatch(ItemStack is) { + int savedCollected = getCollectedItemCount(is); + if (is != null) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedCollected != 0) { + if (is.getCount() + savedCollected >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } + } + + addCollectedItemCount(is); + } + } +} \ No newline at end of file diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java index 878cb3de9..8b1b66af7 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromCraftingItemImplementation.java @@ -10,17 +10,14 @@ import net.minecraftforge.fml.common.gameevent.PlayerEvent; import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; -import com.microsoft.Malmo.MissionHandlers.RewardForItemBase.ItemMatcher; import com.microsoft.Malmo.Schemas.AgentQuitFromCraftingItem; import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithDescription; import com.microsoft.Malmo.Schemas.MissionInit; /** - * * @author Cayden Codel, Carnegie Mellon University - * - * Gives agents rewards when items are crafted. * + * Gives agents rewards when items are crafted. Handles variants and colors. */ public class AgentQuitFromCraftingItemImplementation extends HandlerBase implements IWantToQuit { @@ -28,8 +25,8 @@ public class AgentQuitFromCraftingItemImplementation extends HandlerBase impleme private HashMap craftedItems; private List matchers; private String quitCode = ""; - boolean wantToQuit = false; - boolean callCraft = true; + private boolean wantToQuit = false; + private boolean callCraft = true; public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { String description; @@ -46,7 +43,7 @@ String description() { @Override public boolean parseParameters(Object params) { - if (params == null || !(params instanceof AgentQuitFromCraftingItem)) + if (!(params instanceof AgentQuitFromCraftingItem)) return false; this.params = (AgentQuitFromCraftingItem) params; @@ -85,8 +82,16 @@ public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { callCraft = !callCraft; } + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ private boolean getVariant(ItemStack is) { - for (ItemMatcher matcher : matchers) { + for (ItemQuitMatcher matcher : matchers) { if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) return true; @@ -106,26 +111,22 @@ private int getCraftedItemCount(ItemStack is) { else return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getItem().getUnlocalizedName()); - } private void addCraftedItemCount(ItemStack is) { boolean variant = getVariant(is); - if (variant) { - int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 - : craftedItems.get(is.getUnlocalizedName())); + int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getUnlocalizedName())); + if (variant) craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - } else { - int prev = (craftedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 - : craftedItems.get(is.getItem().getUnlocalizedName())); + else craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - } } private void checkForMatch(ItemStack is) { int savedCrafted = getCraftedItemCount(is); - if (is != null && is.getItem() != null) { + if (is != null) { for (ItemQuitMatcher matcher : this.matchers) { if (matcher.matches(is)) { if (savedCrafted != 0) { diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java index 380e2f928..1629cf061 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java @@ -4,28 +4,35 @@ import java.util.HashMap; import java.util.List; +import com.microsoft.Malmo.Schemas.AgentQuitFromPossessingItem; import net.minecraft.item.ItemStack; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.entity.player.EntityItemPickupEvent; import net.minecraftforge.event.entity.item.ItemTossEvent; -import net.minecraftforge.fml.common.gameevent.PlayerEvent; +import net.minecraftforge.event.entity.player.EntityItemPickupEvent; +import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent; +import net.minecraftforge.event.world.BlockEvent.PlaceEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; -import com.microsoft.Malmo.MissionHandlers.AgentQuitFromCraftingItemImplementation.ItemQuitMatcher; import com.microsoft.Malmo.MissionHandlers.RewardForCollectingItemImplementation.GainItemEvent; -import com.microsoft.Malmo.MissionHandlers.RewardForItemBase.ItemMatcher; -import com.microsoft.Malmo.Schemas.AgentQuitFromPossessingItem; +import com.microsoft.Malmo.MissionHandlers.RewardForDiscardingItemImplementation.LoseItemEvent; import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithDescription; import com.microsoft.Malmo.Schemas.MissionInit; +/** + * @author Cayden Codel, Carnegie Mellon University + *

+ * Quits the mission when the agent has possessed the right amount of items. The count on the item collection is non-absolute. + *

+ * In order to quit the mission, the agent must have the requisite items in its inventory all at one time. + */ public class AgentQuitFromPossessingItemImplementation extends HandlerBase implements IWantToQuit { - AgentQuitFromPossessingItem params; + + private AgentQuitFromPossessingItem params; private HashMap collectedItems; - List matchers; - String quitCode = ""; - boolean wantToQuit = false; - boolean callCraft = true; + private List matchers; + private String quitCode = ""; + private boolean wantToQuit = false; public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { String description; @@ -42,7 +49,7 @@ String description() { @Override public boolean parseParameters(Object params) { - if (params == null || !(params instanceof AgentQuitFromPossessingItem)) + if (!(params instanceof AgentQuitFromPossessingItem)) return false; this.params = (AgentQuitFromPossessingItem) params; @@ -75,36 +82,49 @@ public void cleanup() { @SubscribeEvent public void onGainItem(GainItemEvent event) { - System.out.println("Gained an item: " + event.stack.getUnlocalizedName()); checkForMatch(event.stack); } @SubscribeEvent public void onPickupItem(EntityItemPickupEvent event) { - if (event.getItem() != null && event.getItem().getEntityItem() != null) { - ItemStack stack = event.getItem().getEntityItem(); - checkForMatch(stack); - } + if (event.getItem() != null) + checkForMatch(event.getItem().getEntityItem()); } @SubscribeEvent - public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { - if (callCraft) - checkForMatch(event.crafting); + public void onLoseItem(LoseItemEvent event) { + if (event.stack != null) + removeCollectedItemCount(event.stack); + } - callCraft = !callCraft; + @SubscribeEvent + public void onDropItem(ItemTossEvent event) { + removeCollectedItemCount(event.getEntityItem().getEntityItem()); + } + + @SubscribeEvent + public void onDestroyItem(PlayerDestroyItemEvent event) { + removeCollectedItemCount(event.getOriginal()); } @SubscribeEvent - public void onItemToss(ItemTossEvent event) { - if (event.getEntityItem() != null && event.getEntityItem().getEntityItem() != null) { - ItemStack stack = event.getEntityItem().getEntityItem(); - removeCollectedItem(stack); + public void onBlockPlace(PlaceEvent event) { + if (!event.isCanceled() && event.getPlacedBlock() != null) { + ItemStack stack = new ItemStack(event.getPlacedBlock().getBlock()); + removeCollectedItemCount(stack); } } + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ private boolean getVariant(ItemStack is) { - for (ItemMatcher matcher : matchers) { + for (ItemQuitMatcher matcher : matchers) { if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) return true; @@ -116,53 +136,46 @@ private boolean getVariant(ItemStack is) { return false; } - private int getCraftedItemCount(ItemStack is) { + private void addCollectedItemCount(ItemStack is) { boolean variant = getVariant(is); + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); if (variant) - return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 - : collectedItems.get(is.getUnlocalizedName()); + collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); else - return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 - : collectedItems.get(is.getItem().getUnlocalizedName()); + collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); } - private void addCollectedItem(ItemStack is) { + private void removeCollectedItemCount(ItemStack is) { boolean variant = getVariant(is); - if (variant) { - int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getUnlocalizedName())); - collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - } else { - int prev = (collectedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getItem().getUnlocalizedName())); - collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - } + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + if (variant) + collectedItems.put(is.getUnlocalizedName(), prev - is.getCount()); + else + collectedItems.put(is.getItem().getUnlocalizedName(), prev - is.getCount()); } - private void removeCollectedItem(ItemStack is) { + private int getCollectedItemCount(ItemStack is) { boolean variant = getVariant(is); - if (variant) { - int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getUnlocalizedName())); - collectedItems.put(is.getUnlocalizedName(), Integer.max(0, prev - is.getCount())); - } else { - int prev = (collectedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getItem().getUnlocalizedName())); - collectedItems.put(is.getItem().getUnlocalizedName(), Integer.max(0, prev - is.getCount())); - } + if (variant) + return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 : collectedItems.get(is.getUnlocalizedName()); + else + return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName()); } private void checkForMatch(ItemStack is) { - int savedCrafted = getCraftedItemCount(is); - if (is != null && is.getItem() != null) { + int savedCollected = getCollectedItemCount(is); + if (is != null) { for (ItemQuitMatcher matcher : this.matchers) { if (matcher.matches(is)) { - if (savedCrafted != 0) { - if (is.getCount() + savedCrafted >= matcher.matchSpec.getAmount()) { + if (savedCollected != 0) { + if (is.getCount() + savedCollected >= matcher.matchSpec.getAmount()) { this.quitCode = matcher.description(); this.wantToQuit = true; } @@ -173,7 +186,7 @@ private void checkForMatch(ItemStack is) { } } - addCollectedItem(is); + addCollectedItemCount(is); } } -} +} \ No newline at end of file diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java index 9ebc9caf6..1ab383b99 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java @@ -16,131 +16,137 @@ import com.microsoft.Malmo.Schemas.MissionInit; /** - * * @author Cayden Codel, Carnegie Mellon University - * - * Gives agents rewards when items are smelted. - * + *

+ * Gives agents rewards when items are smelted. Handles variants and colors. */ public class AgentQuitFromSmeltingItemImplementation extends HandlerBase implements IWantToQuit { - private AgentQuitFromSmeltingItem params; - private HashMap smeltedItems; - private List matchers; - private String quitCode = ""; - boolean wantToQuit = false; - boolean callSmelt = true; - - public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { - String description; - - ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { - super(spec); - this.description = spec.getDescription(); - } - - String description() { - return this.description; - } - } - - @Override - public boolean parseParameters(Object params) { - if (params == null || !(params instanceof AgentQuitFromSmeltingItem)) - return false; - - this.params = (AgentQuitFromSmeltingItem) params; - this.matchers = new ArrayList(); - for (BlockOrItemSpecWithDescription bs : this.params.getItem()) - this.matchers.add(new ItemQuitMatcher(bs)); - return true; - } - - @Override - public boolean doIWantToQuit(MissionInit missionInit) { - return this.wantToQuit; - } - - @Override - public String getOutcome() { - return this.quitCode; - } - - @Override - public void prepare(MissionInit missionInit) { - MinecraftForge.EVENT_BUS.register(this); - smeltedItems = new HashMap(); - } - - @Override - public void cleanup() { - MinecraftForge.EVENT_BUS.unregister(this); - } - - @SubscribeEvent - public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { - if (callSmelt) - checkForMatch(event.smelting); - - callSmelt = !callSmelt; - } - - private boolean getVariant(ItemStack is) { - for (ItemMatcher matcher : matchers) { - if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { - if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) - return true; - if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) - return true; - } - } - - return false; - } - - private int getSmeltedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) - return (smeltedItems.get(is.getUnlocalizedName()) == null) ? 0 : smeltedItems.get(is.getUnlocalizedName()); - else - return (smeltedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 - : smeltedItems.get(is.getItem().getUnlocalizedName()); - - } - - private void addSmeltedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) { - int prev = (smeltedItems.get(is.getUnlocalizedName()) == null ? 0 - : smeltedItems.get(is.getUnlocalizedName())); - smeltedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - } else { - int prev = (smeltedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 - : smeltedItems.get(is.getItem().getUnlocalizedName())); - smeltedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - } - } - - private void checkForMatch(ItemStack is) { - int savedSmelted = getSmeltedItemCount(is); - if (is != null && is.getItem() != null) { - for (ItemQuitMatcher matcher : this.matchers) { - if (matcher.matches(is)) { - if (savedSmelted != 0) { - if (is.getCount() + savedSmelted >= matcher.matchSpec.getAmount()) { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } else if (is.getCount() >= matcher.matchSpec.getAmount()) { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } - } - - addSmeltedItemCount(is); - } - } + private AgentQuitFromSmeltingItem params; + private HashMap smeltedItems; + private List matchers; + private String quitCode = ""; + private boolean wantToQuit = false; + private boolean callSmelt = true; + + public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { + String description; + + ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { + super(spec); + this.description = spec.getDescription(); + } + + String description() { + return this.description; + } + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof AgentQuitFromSmeltingItem)) + return false; + + this.params = (AgentQuitFromSmeltingItem) params; + this.matchers = new ArrayList(); + for (BlockOrItemSpecWithDescription bs : this.params.getItem()) + this.matchers.add(new ItemQuitMatcher(bs)); + return true; + } + + @Override + public boolean doIWantToQuit(MissionInit missionInit) { + return this.wantToQuit; + } + + @Override + public String getOutcome() { + return this.quitCode; + } + + @Override + public void prepare(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.register(this); + smeltedItems = new HashMap(); + } + + @Override + public void cleanup() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { + if (callSmelt) + checkForMatch(event.smelting); + + callSmelt = !callSmelt; + } + + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getSmeltedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (smeltedItems.get(is.getUnlocalizedName()) == null) ? 0 : smeltedItems.get(is.getUnlocalizedName()); + else + return (smeltedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : smeltedItems.get(is.getItem().getUnlocalizedName()); + + } + + private void addSmeltedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) { + int prev = (smeltedItems.get(is.getUnlocalizedName()) == null ? 0 + : smeltedItems.get(is.getUnlocalizedName())); + smeltedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + } else { + int prev = (smeltedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 + : smeltedItems.get(is.getItem().getUnlocalizedName())); + smeltedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + } + + private void checkForMatch(ItemStack is) { + int savedSmelted = getSmeltedItemCount(is); + if (is != null) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedSmelted != 0) { + if (is.getCount() + savedSmelted >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } + } + + addSmeltedItemCount(is); + } + } } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCollectingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCollectingItemImplementation.java index 6907e56d2..ef775b916 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCollectingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCollectingItemImplementation.java @@ -1,31 +1,19 @@ -// -------------------------------------------------------------------------------------------------- -// Copyright (c) 2016 Microsoft Corporation -// -// 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 com.microsoft.Malmo.MissionHandlers; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; - +import java.util.ArrayList; +import java.util.HashMap; import java.util.Map; -import javax.xml.bind.DatatypeConverter; +import com.microsoft.Malmo.MalmoMod; +import com.microsoft.Malmo.MalmoMod.IMalmoMessageListener; +import com.microsoft.Malmo.MalmoMod.MalmoMessageType; +import com.microsoft.Malmo.MissionHandlerInterfaces.IRewardProducer; +import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithReward; +import com.microsoft.Malmo.Schemas.MissionInit; +import com.microsoft.Malmo.Schemas.RewardForCollectingItem; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; import net.minecraftforge.common.MinecraftForge; @@ -34,95 +22,171 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.network.ByteBufUtils; -import com.microsoft.Malmo.MalmoMod; -import com.microsoft.Malmo.MalmoMod.IMalmoMessageListener; -import com.microsoft.Malmo.MalmoMod.MalmoMessageType; -import com.microsoft.Malmo.MissionHandlerInterfaces.IRewardProducer; -import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithReward; -import com.microsoft.Malmo.Schemas.MissionInit; -import com.microsoft.Malmo.Schemas.RewardForCollectingItem; +import javax.xml.bind.DatatypeConverter; + +/** + * @author Cayden Codel, Carnegie Mellon University + *

+ * Sends a reward when the agent collected the specified item with + * specified amounts. Counter is absolute. + */ +public class RewardForCollectingItemImplementation extends RewardForItemBase + implements IRewardProducer, IMalmoMessageListener { -public class RewardForCollectingItemImplementation extends RewardForItemBase implements IRewardProducer, IMalmoMessageListener -{ private RewardForCollectingItem params; + private ArrayList matchers; + private HashMap craftedItems; - @Override - public void onMessage(MalmoMessageType messageType, Map data) - { - String bufstring = data.get("message"); - ByteBuf buf = Unpooled.copiedBuffer(DatatypeConverter.parseBase64Binary(bufstring)); - ItemStack itemStack = ByteBufUtils.readItemStack(buf); - if (itemStack != null && itemStack.getItem() != null) - { - accumulateReward(this.params.getDimension(), itemStack); + @SubscribeEvent + public void onPickupItem(EntityItemPickupEvent event) { + if (event.getItem() != null) { + checkForMatch(event.getItem().getEntityItem()); + if (event.getEntityPlayer() instanceof EntityPlayerMP) + sendItemStackToClient((EntityPlayerMP) event.getEntityPlayer(), MalmoMessageType.SERVER_COLLECTITEM, event.getItem().getEntityItem()); } - else - { - System.out.println("Error - couldn't understand the itemstack we received."); + } + + @SubscribeEvent + public void onGainItem(GainItemEvent event) { + if (event.stack != null) { + accumulateReward(this.params.getDimension(), event.stack); } } - - public static class GainItemEvent extends Event - { - public final ItemStack stack; - public GainItemEvent(ItemStack stack) - { - this.stack = stack; + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } } + + return false; } - @Override - public boolean parseParameters(Object params) { - if (params == null || !(params instanceof RewardForCollectingItem)) - return false; + private int getCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); - // Build up a map of rewards per item: - this.params = (RewardForCollectingItem) params; - for (BlockOrItemSpecWithReward is : this.params.getItem()) - addItemSpecToRewardStructure(is); + if (variant) + return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); + else + return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName()); + } - return true; + private void addCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getUnlocalizedName())); + if (variant) + craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + else + craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); } - @SubscribeEvent - public void onGainItem(GainItemEvent event) - { - if (event.stack != null) - { - accumulateReward(this.params.getDimension(), event.stack); + private void checkForMatch(ItemStack is) { + int savedCollected = getCollectedItemCount(is); + if (is != null) { + for (ItemMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (!params.isSparse()) { + if (savedCollected != 0 && savedCollected < matcher.matchSpec.getAmount()) { + for (int i = savedCollected; i < matcher.matchSpec.getAmount() + && i - savedCollected < is.getCount(); i++) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + + } else if (savedCollected != 0 && savedCollected >= matcher.matchSpec.getAmount()) { + // Do nothing + } else { + for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } else { + if (savedCollected < matcher.matchSpec.getAmount() + && savedCollected + is.getCount() >= matcher.matchSpec.getAmount()) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } + } + + addCollectedItemCount(is); } } - @SubscribeEvent - public void onPickupItem(EntityItemPickupEvent event) - { - if (event.getItem() != null && event.getEntityPlayer() instanceof EntityPlayerMP ) - { - // This event is received on the server side, so we need to pass it to the client. - sendItemStackToClient((EntityPlayerMP)event.getEntityPlayer(), MalmoMessageType.SERVER_COLLECTITEM, event.getItem().getEntityItem()); - } + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof RewardForCollectingItem)) + return false; + + matchers = new ArrayList(); + + this.params = (RewardForCollectingItem) params; + for (BlockOrItemSpecWithReward spec : this.params.getItem()) + this.matchers.add(new ItemMatcher(spec)); + + return true; } @Override - public void prepare(MissionInit missionInit) - { + public void prepare(MissionInit missionInit) { super.prepare(missionInit); MinecraftForge.EVENT_BUS.register(this); MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + craftedItems = new HashMap(); } @Override - public void getReward(MissionInit missionInit, MultidimensionalReward reward) - { + public void getReward(MissionInit missionInit, MultidimensionalReward reward) { super.getReward(missionInit, reward); } @Override - public void cleanup() - { + public void cleanup() { super.cleanup(); MinecraftForge.EVENT_BUS.unregister(this); MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); } -} + + @Override + public void onMessage(MalmoMessageType messageType, Map data) { + String buffString = data.get("message"); + ByteBuf buf = Unpooled.copiedBuffer(DatatypeConverter.parseBase64Binary(buffString)); + ItemStack itemStack = ByteBufUtils.readItemStack(buf); + if (itemStack != null) { + accumulateReward(this.params.getDimension(), itemStack); + } else { + System.out.println("Error - couldn't understand the itemstack we received."); + } + } + + public static class GainItemEvent extends Event { + public final ItemStack stack; + + public GainItemEvent(ItemStack stack) { + this.stack = stack; + } + } +} \ No newline at end of file diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java index 8329fddd6..0b6ed8030 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForCraftingItemImplementation.java @@ -18,154 +18,145 @@ import net.minecraftforge.fml.common.gameevent.PlayerEvent; /** - * * @author Cayden Codel, Carnegie Mellon University - * - * Sends a reward when the agent crafts the specified item with - * specified amounts. + *

+ * Sends a reward when the agent crafts the specified item with + * specified amounts. */ public class RewardForCraftingItemImplementation extends RewardForItemBase - implements IRewardProducer, IMalmoMessageListener { - - private RewardForCraftingItem params; - private ArrayList matchers; - private HashMap craftedItems; - boolean callCraft = true; - - @SubscribeEvent - public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { - if (callCraft) - checkForMatch(event.crafting); - - callCraft = !callCraft; - } - - private boolean getVariant(ItemStack is) { - for (ItemMatcher matcher : matchers) { - if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { - if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) - return true; - if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) - return true; - } - } - - return false; - } - - private int getCraftedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) - return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); - else - return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 - : craftedItems.get(is.getItem().getUnlocalizedName()); - - } - - private void addCraftedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) { - int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 - : craftedItems.get(is.getUnlocalizedName())); - craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - } else { - int prev = (craftedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 - : craftedItems.get(is.getItem().getUnlocalizedName())); - craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - } - } - - private void checkForMatch(ItemStack is) { - //System.out.println("Checking for match on " + is.getItem().getUnlocalizedName()); - int savedCrafted = getCraftedItemCount(is); - //System.out.println("Previous saved amount is " + savedCrafted); - if (is != null && is.getItem() != null) { - for (ItemMatcher matcher : this.matchers) { - if (matcher.matches(is)) { - if (!params.isSparse()) { - if (savedCrafted != 0 && savedCrafted < matcher.matchSpec.getAmount()) { - for (int i = savedCrafted; i < matcher.matchSpec.getAmount() - && i - savedCrafted < is.getCount(); i++) { - //System.out.println("Sparse, had nonzero saved crafted amount, giving a reward of " - // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); - this.adjustAndDistributeReward( - ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), - params.getDimension(), - ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); - } - - } else if (savedCrafted != 0 && savedCrafted >= matcher.matchSpec.getAmount()) { - // Do nothing - //System.out - // .println("Sparse, had nonzero saved crafted amount, but not enough new for reward"); - } else { - for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { - //System.out.println("Had zero saved crafted amount, giving a reward of " - // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); - this.adjustAndDistributeReward( - ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), - params.getDimension(), - ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); - } - - } - } else { - if (savedCrafted < matcher.matchSpec.getAmount() - && savedCrafted + is.getCount() >= matcher.matchSpec.getAmount()) { - //System.out.println("Not sparse, giving a reward of " - // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); - this.adjustAndDistributeReward( - ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), - params.getDimension(), - ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); - } - } - } - } - - addCraftedItemCount(is); - } - - } - - @Override - public boolean parseParameters(Object params) { - if (params == null || !(params instanceof RewardForCraftingItem)) - return false; - - matchers = new ArrayList(); - - this.params = (RewardForCraftingItem) params; - for (BlockOrItemSpecWithReward spec : this.params.getItem()) - this.matchers.add(new ItemMatcher(spec)); - - return true; - } - - @Override - public void prepare(MissionInit missionInit) { - super.prepare(missionInit); - MinecraftForge.EVENT_BUS.register(this); - MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); - craftedItems = new HashMap(); - } - - @Override - public void getReward(MissionInit missionInit, MultidimensionalReward reward) { - super.getReward(missionInit, reward); - } - - @Override - public void cleanup() { - super.cleanup(); - MinecraftForge.EVENT_BUS.unregister(this); - MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); - } - - @Override - public void onMessage(MalmoMessageType messageType, Map data) { - } -} + implements IRewardProducer, IMalmoMessageListener { + + private RewardForCraftingItem params; + private ArrayList matchers; + private HashMap craftedItems; + private boolean callCraft = true; + + @SubscribeEvent + public void onItemCraft(PlayerEvent.ItemCraftedEvent event) { + if (callCraft) + checkForMatch(event.crafting); + + callCraft = !callCraft; + } + + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); + else + return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName()); + } + + private void addCraftedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getUnlocalizedName())); + if (variant) + craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + else + craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + + private void checkForMatch(ItemStack is) { + int savedCrafted = getCraftedItemCount(is); + if (is != null) { + for (ItemMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (!params.isSparse()) { + if (savedCrafted != 0 && savedCrafted < matcher.matchSpec.getAmount()) { + for (int i = savedCrafted; i < matcher.matchSpec.getAmount() + && i - savedCrafted < is.getCount(); i++) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + + } else if (savedCrafted != 0 && savedCrafted >= matcher.matchSpec.getAmount()) { + // Do nothing + } else { + for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } else { + if (savedCrafted < matcher.matchSpec.getAmount() + && savedCrafted + is.getCount() >= matcher.matchSpec.getAmount()) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } + } + + addCraftedItemCount(is); + } + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof RewardForCraftingItem)) + return false; + + matchers = new ArrayList(); + + this.params = (RewardForCraftingItem) params; + for (BlockOrItemSpecWithReward spec : this.params.getItem()) + this.matchers.add(new ItemMatcher(spec)); + + return true; + } + + @Override + public void prepare(MissionInit missionInit) { + super.prepare(missionInit); + MinecraftForge.EVENT_BUS.register(this); + MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + craftedItems = new HashMap(); + } + + @Override + public void getReward(MissionInit missionInit, MultidimensionalReward reward) { + super.getReward(missionInit, reward); + } + + @Override + public void cleanup() { + super.cleanup(); + MinecraftForge.EVENT_BUS.unregister(this); + MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + } + + @Override + public void onMessage(MalmoMessageType messageType, Map data) { + } +} \ No newline at end of file diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForPossessingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForPossessingItemImplementation.java new file mode 100644 index 000000000..33473a80b --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForPossessingItemImplementation.java @@ -0,0 +1,232 @@ +package com.microsoft.Malmo.MissionHandlers; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import com.microsoft.Malmo.MalmoMod; +import com.microsoft.Malmo.MalmoMod.IMalmoMessageListener; +import com.microsoft.Malmo.MalmoMod.MalmoMessageType; +import com.microsoft.Malmo.MissionHandlerInterfaces.IRewardProducer; +import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithReward; +import com.microsoft.Malmo.Schemas.MissionInit; +import com.microsoft.Malmo.MissionHandlers.RewardForDiscardingItemImplementation.LoseItemEvent; +import com.microsoft.Malmo.Schemas.RewardForPossessingItem; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.item.ItemTossEvent; +import net.minecraftforge.event.entity.player.EntityItemPickupEvent; +import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent; +import net.minecraftforge.event.world.BlockEvent.PlaceEvent; +import net.minecraftforge.fml.common.eventhandler.Event; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.ByteBufUtils; + +import javax.xml.bind.DatatypeConverter; + +/** + * @author Cayden Codel, Carnegie Mellon University + *

+ * Sends a reward when the agent possesses the specified item with + * specified amounts. The counter is relative, meaning it goes down if items are placed, lost, or destroyed. + */ +public class RewardForPossessingItemImplementation extends RewardForItemBase + implements IRewardProducer, IMalmoMessageListener { + + private RewardForPossessingItem params; + private ArrayList matchers; + private HashMap collectedItems; + + @SubscribeEvent + public void onPickupItem(EntityItemPickupEvent event) { + if (event.getItem() != null) { + checkForMatch(event.getItem().getEntityItem()); + if (event.getEntityPlayer() instanceof EntityPlayerMP) + sendItemStackToClient((EntityPlayerMP) event.getEntityPlayer(), MalmoMessageType.SERVER_COLLECTITEM, event.getItem().getEntityItem()); + } + } + + @SubscribeEvent + public void onGainItem(GainItemEvent event) { + if (event.stack != null) { + accumulateReward(this.params.getDimension(), event.stack); + } + } + + @SubscribeEvent + public void onLoseItem(LoseItemEvent event) { + if (event.stack != null) + removeCollectedItemCount(event.stack); + } + + @SubscribeEvent + public void onDropItem(ItemTossEvent event) { + removeCollectedItemCount(event.getEntityItem().getEntityItem()); + } + + @SubscribeEvent + public void onDestroyItem(PlayerDestroyItemEvent event) { + removeCollectedItemCount(event.getOriginal()); + } + + @SubscribeEvent + public void onBlockPlace(PlaceEvent event) { + if (!event.isCanceled() && event.getPlacedBlock() != null) { + ItemStack stack = new ItemStack(event.getPlacedBlock().getBlock()); + removeCollectedItemCount(stack); + } + } + + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 : collectedItems.get(is.getUnlocalizedName()); + else + return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName()); + } + + private void addCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + if (variant) + collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + else + collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + + private void removeCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + if (variant) + collectedItems.put(is.getUnlocalizedName(), prev - is.getCount()); + else + collectedItems.put(is.getItem().getUnlocalizedName(), prev - is.getCount()); + } + + private void checkForMatch(ItemStack is) { + int savedCollected = getCollectedItemCount(is); + if (is != null) { + for (ItemMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (!params.isSparse()) { + if (savedCollected != 0 && savedCollected < matcher.matchSpec.getAmount()) { + for (int i = savedCollected; i < matcher.matchSpec.getAmount() + && i - savedCollected < is.getCount(); i++) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + + } else if (savedCollected != 0 && savedCollected >= matcher.matchSpec.getAmount()) { + // Do nothing + } else { + for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } else { + if (savedCollected < matcher.matchSpec.getAmount() + && savedCollected + is.getCount() >= matcher.matchSpec.getAmount()) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } + } + + addCollectedItemCount(is); + } + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof RewardForPossessingItem)) + return false; + + matchers = new ArrayList(); + + this.params = (RewardForPossessingItem) params; + for (BlockOrItemSpecWithReward spec : this.params.getItem()) + this.matchers.add(new ItemMatcher(spec)); + + return true; + } + + @Override + public void prepare(MissionInit missionInit) { + super.prepare(missionInit); + MinecraftForge.EVENT_BUS.register(this); + MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + collectedItems = new HashMap(); + } + + @Override + public void getReward(MissionInit missionInit, MultidimensionalReward reward) { + super.getReward(missionInit, reward); + } + + @Override + public void cleanup() { + super.cleanup(); + MinecraftForge.EVENT_BUS.unregister(this); + MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + } + + @Override + public void onMessage(MalmoMessageType messageType, Map data) { + String buffString = data.get("message"); + ByteBuf buf = Unpooled.copiedBuffer(DatatypeConverter.parseBase64Binary(buffString)); + ItemStack itemStack = ByteBufUtils.readItemStack(buf); + if (itemStack != null) { + accumulateReward(this.params.getDimension(), itemStack); + } else { + System.out.println("Error - couldn't understand the itemstack we received."); + } + } + + public static class GainItemEvent extends Event { + public final ItemStack stack; + + public GainItemEvent(ItemStack stack) { + this.stack = stack; + } + } +} \ No newline at end of file diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java index ee4a5fded..3b6bae305 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java @@ -10,27 +10,26 @@ import com.microsoft.Malmo.MissionHandlerInterfaces.IRewardProducer; import com.microsoft.Malmo.Schemas.BlockOrItemSpecWithReward; import com.microsoft.Malmo.Schemas.MissionInit; -import com.microsoft.Malmo.Schemas.RewardForSmeltingItem; +import com.microsoft.Malmo.Schemas.RewardForSmeltingItem; import net.minecraft.item.ItemStack; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.PlayerEvent; /** - * * @author Cayden Codel, Carnegie Mellon University - * - * Sends a reward when the agent smelts the specified item with - * specified amounts. + *

+ * Sends a reward when the agent smelts the specified item with + * specified amounts. */ public class RewardForSmeltingItemImplementation extends RewardForItemBase implements IRewardProducer, IMalmoMessageListener { private RewardForSmeltingItem params; private ArrayList matchers; - private HashMap smeltedItems; - boolean callSmelt = true; + private HashMap craftedItems; + private boolean callSmelt = true; @SubscribeEvent public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { @@ -40,6 +39,14 @@ public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { callSmelt = !callSmelt; } + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ private boolean getVariant(ItemStack is) { for (ItemMatcher matcher : matchers) { if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { @@ -53,70 +60,55 @@ private boolean getVariant(ItemStack is) { return false; } - private int getCraftedItemCount(ItemStack is) { + private int getSmeltedItemCount(ItemStack is) { boolean variant = getVariant(is); if (variant) - return (smeltedItems.get(is.getUnlocalizedName()) == null) ? 0 : smeltedItems.get(is.getUnlocalizedName()); + return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); else - return (smeltedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 - : smeltedItems.get(is.getItem().getUnlocalizedName()); - + return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName()); } private void addSmeltedItemCount(ItemStack is) { boolean variant = getVariant(is); - if (variant) { - int prev = (smeltedItems.get(is.getUnlocalizedName()) == null ? 0 - : smeltedItems.get(is.getUnlocalizedName())); - smeltedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - } else { - int prev = (smeltedItems.get(is.getItem().getUnlocalizedName()) == null ? 0 - : smeltedItems.get(is.getItem().getUnlocalizedName())); - smeltedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - } + int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getUnlocalizedName())); + if (variant) + craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + else + craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); } private void checkForMatch(ItemStack is) { - //System.out.println("Checking for match on " + is.getItem().getUnlocalizedName()); - int savedCrafted = getCraftedItemCount(is); - //System.out.println("Previous saved amount is " + savedCrafted); - if (is != null && is.getItem() != null) { + int savedSmelted = getSmeltedItemCount(is); + if (is != null) { for (ItemMatcher matcher : this.matchers) { if (matcher.matches(is)) { if (!params.isSparse()) { - if (savedCrafted != 0 && savedCrafted < matcher.matchSpec.getAmount()) { - for (int i = savedCrafted; i < matcher.matchSpec.getAmount() - && i - savedCrafted < is.getCount(); i++) { - //System.out.println("Sparse, had nonzero saved crafted amount, giving a reward of " - // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); + if (savedSmelted != 0 && savedSmelted < matcher.matchSpec.getAmount()) { + for (int i = savedSmelted; i < matcher.matchSpec.getAmount() + && i - savedSmelted < is.getCount(); i++) { this.adjustAndDistributeReward( ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), params.getDimension(), ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); } - } else if (savedCrafted != 0 && savedCrafted >= matcher.matchSpec.getAmount()) { + } else if (savedSmelted != 0 && savedSmelted >= matcher.matchSpec.getAmount()) { // Do nothing - //System.out - // .println("Sparse, had nonzero saved crafted amount, but not enough new for reward"); } else { for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { - //System.out.println("Had zero saved crafted amount, giving a reward of " - // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); this.adjustAndDistributeReward( ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), params.getDimension(), ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); } - } } else { - if (savedCrafted < matcher.matchSpec.getAmount() - && savedCrafted + is.getCount() >= matcher.matchSpec.getAmount()) { - //System.out.println("Not sparse, giving a reward of " - // + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue()); + if (savedSmelted < matcher.matchSpec.getAmount() + && savedSmelted + is.getCount() >= matcher.matchSpec.getAmount()) { this.adjustAndDistributeReward( ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), params.getDimension(), @@ -128,12 +120,11 @@ private void checkForMatch(ItemStack is) { addSmeltedItemCount(is); } - } @Override public boolean parseParameters(Object params) { - if (params == null || !(params instanceof RewardForSmeltingItem)) + if (!(params instanceof RewardForSmeltingItem)) return false; matchers = new ArrayList(); @@ -150,7 +141,7 @@ public void prepare(MissionInit missionInit) { super.prepare(missionInit); MinecraftForge.EVENT_BUS.register(this); MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); - smeltedItems = new HashMap(); + craftedItems = new HashMap(); } @Override @@ -168,4 +159,4 @@ public void cleanup() { @Override public void onMessage(MalmoMessageType messageType, Map data) { } -} +} \ No newline at end of file diff --git a/Schemas/Mission.xsd b/Schemas/Mission.xsd index 8b6a1e8aa..6fe39f44c 100644 --- a/Schemas/Mission.xsd +++ b/Schemas/Mission.xsd @@ -358,6 +358,7 @@ + @@ -380,9 +381,9 @@ + - diff --git a/Schemas/Mission.xsd.in b/Schemas/Mission.xsd.in index bc8a8e3cc..d9a7be0f9 100644 --- a/Schemas/Mission.xsd.in +++ b/Schemas/Mission.xsd.in @@ -358,6 +358,7 @@ + @@ -380,9 +381,9 @@ + - diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd index 32a8064cb..5390b4141 100644 --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -2253,12 +2253,36 @@ Sends a reward when the agent collects a specific item. + + If Sparse is set to true, will only give full reward on collecting entire amount. + + Otherwise, will give the reward amount notated for each item collected up to the amount noted. + + + + + + + + + Sends a reward when the agent collects a specific item. + + If Sparse is set to true, will only give full reward on possessing the entire amount. + + Otherwise, will give the rewards amount notated for each item crafted up to the amount noted. + + + + + + + @@ -2277,7 +2301,7 @@ - + @@ -2296,7 +2320,7 @@ - + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index cc303a351..eda5db440 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -2252,12 +2252,36 @@ Sends a reward when the agent collects a specific item. + + If Sparse is set to true, will only give full reward on collecting entire amount. + + Otherwise, will give the reward amount notated for each item collected up to the amount noted. + + + + + + + + + Sends a reward when the agent collects a specific item. + + If Sparse is set to true, will only give full reward on possessing the entire amount. + + Otherwise, will give the rewards amount notated for each item crafted up to the amount noted. + + + + + + + @@ -2276,7 +2300,7 @@ - + @@ -2295,7 +2319,7 @@ - + From 6c8586f27c592d28aeafdee2be78e1b5ef589710 Mon Sep 17 00:00:00 2001 From: ccodel Date: Fri, 8 Feb 2019 23:09:58 -0500 Subject: [PATCH 20/40] Updated smelting to call matcher once every four now --- ...entQuitFromSmeltingItemImplementation.java | 26 +- .../RewardForSmeltingItemImplementation.java | 270 +++++++++--------- 2 files changed, 147 insertions(+), 149 deletions(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java index 1ab383b99..269317a92 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromSmeltingItemImplementation.java @@ -27,7 +27,7 @@ public class AgentQuitFromSmeltingItemImplementation extends HandlerBase impleme private List matchers; private String quitCode = ""; private boolean wantToQuit = false; - private boolean callSmelt = true; + private int callSmelt = 0; public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { String description; @@ -77,10 +77,10 @@ public void cleanup() { @SubscribeEvent public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { - if (callSmelt) + if (callSmelt % 4 == 0) checkForMatch(event.smelting); - callSmelt = !callSmelt; + callSmelt = (callSmelt + 1) % 4; } /** @@ -131,22 +131,20 @@ private void addSmeltedItemCount(ItemStack is) { private void checkForMatch(ItemStack is) { int savedSmelted = getSmeltedItemCount(is); - if (is != null) { - for (ItemQuitMatcher matcher : this.matchers) { - if (matcher.matches(is)) { - if (savedSmelted != 0) { - if (is.getCount() + savedSmelted >= matcher.matchSpec.getAmount()) { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedSmelted != 0) { + if (is.getCount() + savedSmelted >= matcher.matchSpec.getAmount()) { this.quitCode = matcher.description(); this.wantToQuit = true; } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; } } - - addSmeltedItemCount(is); } + + addSmeltedItemCount(is); } } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java index 3b6bae305..9eee04e9b 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java @@ -24,139 +24,139 @@ * specified amounts. */ public class RewardForSmeltingItemImplementation extends RewardForItemBase - implements IRewardProducer, IMalmoMessageListener { - - private RewardForSmeltingItem params; - private ArrayList matchers; - private HashMap craftedItems; - private boolean callSmelt = true; - - @SubscribeEvent - public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { - if (callSmelt) - checkForMatch(event.smelting); - - callSmelt = !callSmelt; - } - - /** - * Checks whether the ItemStack matches a variant stored in the item list. If - * so, returns true, else returns false. - * - * @param is The item stack - * @return If the stack is allowed in the item matchers and has color or - * variants enabled, returns true, else false. - */ - private boolean getVariant(ItemStack is) { - for (ItemMatcher matcher : matchers) { - if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { - if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) - return true; - if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) - return true; - } - } - - return false; - } - - private int getSmeltedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) - return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); - else - return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 - : craftedItems.get(is.getItem().getUnlocalizedName()); - } - - private void addSmeltedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 - : craftedItems.get(is.getUnlocalizedName())); - if (variant) - craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - else - craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - } - - private void checkForMatch(ItemStack is) { - int savedSmelted = getSmeltedItemCount(is); - if (is != null) { - for (ItemMatcher matcher : this.matchers) { - if (matcher.matches(is)) { - if (!params.isSparse()) { - if (savedSmelted != 0 && savedSmelted < matcher.matchSpec.getAmount()) { - for (int i = savedSmelted; i < matcher.matchSpec.getAmount() - && i - savedSmelted < is.getCount(); i++) { - this.adjustAndDistributeReward( - ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), - params.getDimension(), - ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); - } - - } else if (savedSmelted != 0 && savedSmelted >= matcher.matchSpec.getAmount()) { - // Do nothing - } else { - for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { - this.adjustAndDistributeReward( - ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), - params.getDimension(), - ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); - } - } - } else { - if (savedSmelted < matcher.matchSpec.getAmount() - && savedSmelted + is.getCount() >= matcher.matchSpec.getAmount()) { - this.adjustAndDistributeReward( - ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), - params.getDimension(), - ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); - } - } - } - } - - addSmeltedItemCount(is); - } - } - - @Override - public boolean parseParameters(Object params) { - if (!(params instanceof RewardForSmeltingItem)) - return false; - - matchers = new ArrayList(); - - this.params = (RewardForSmeltingItem) params; - for (BlockOrItemSpecWithReward spec : this.params.getItem()) - this.matchers.add(new ItemMatcher(spec)); - - return true; - } - - @Override - public void prepare(MissionInit missionInit) { - super.prepare(missionInit); - MinecraftForge.EVENT_BUS.register(this); - MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); - craftedItems = new HashMap(); - } - - @Override - public void getReward(MissionInit missionInit, MultidimensionalReward reward) { - super.getReward(missionInit, reward); - } - - @Override - public void cleanup() { - super.cleanup(); - MinecraftForge.EVENT_BUS.unregister(this); - MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); - } - - @Override - public void onMessage(MalmoMessageType messageType, Map data) { - } + implements IRewardProducer, IMalmoMessageListener { + + private RewardForSmeltingItem params; + private ArrayList matchers; + private HashMap craftedItems; + private int callSmelt = 0; + + @SubscribeEvent + public void onItemSmelt(PlayerEvent.ItemSmeltedEvent event) { + if (callSmelt % 4 == 0) + checkForMatch(event.smelting); + + callSmelt = (callSmelt + 1) % 4; + } + + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ + private boolean getVariant(ItemStack is) { + for (ItemMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private int getSmeltedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (craftedItems.get(is.getUnlocalizedName()) == null) ? 0 : craftedItems.get(is.getUnlocalizedName()); + else + return (craftedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : craftedItems.get(is.getItem().getUnlocalizedName()); + } + + private void addSmeltedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (craftedItems.get(is.getUnlocalizedName()) == null ? 0 + : craftedItems.get(is.getUnlocalizedName())); + if (variant) + craftedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + else + craftedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + } + + private void checkForMatch(ItemStack is) { + int savedSmelted = getSmeltedItemCount(is); + for (ItemMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (!params.isSparse()) { + if (savedSmelted != 0 && savedSmelted < matcher.matchSpec.getAmount()) { + for (int i = savedSmelted; i < matcher.matchSpec.getAmount() + && i - savedSmelted < is.getCount(); i++) { + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + + } else if (savedSmelted != 0 && savedSmelted >= matcher.matchSpec.getAmount()) { + // Do nothing + } else { + for (int i = 0; i < is.getCount() && i < matcher.matchSpec.getAmount(); i++) { + System.out.println("Giving reward"); + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } else { + if (savedSmelted < matcher.matchSpec.getAmount() + && savedSmelted + is.getCount() >= matcher.matchSpec.getAmount()) { + System.out.println("Giving reward"); + this.adjustAndDistributeReward( + ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), + params.getDimension(), + ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); + } + } + } + } + + addSmeltedItemCount(is); + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof RewardForSmeltingItem)) + return false; + + matchers = new ArrayList(); + + this.params = (RewardForSmeltingItem) params; + for (BlockOrItemSpecWithReward spec : this.params.getItem()) + this.matchers.add(new ItemMatcher(spec)); + + return true; + } + + @Override + public void prepare(MissionInit missionInit) { + super.prepare(missionInit); + MinecraftForge.EVENT_BUS.register(this); + MalmoMod.MalmoMessageHandler.registerForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + craftedItems = new HashMap(); + } + + @Override + public void getReward(MissionInit missionInit, MultidimensionalReward reward) { + super.getReward(missionInit, reward); + } + + @Override + public void cleanup() { + super.cleanup(); + MinecraftForge.EVENT_BUS.unregister(this); + MalmoMod.MalmoMessageHandler.deregisterForMessage(this, MalmoMessageType.SERVER_COLLECTITEM); + } + + @Override + public void onMessage(MalmoMessageType messageType, Map data) { + } } \ No newline at end of file From 3b1645723e4c7a6b5a607f9f043a21b78a57c70e Mon Sep 17 00:00:00 2001 From: ccodel Date: Wed, 13 Feb 2019 17:05:07 -0500 Subject: [PATCH 21/40] Implemented nearby handlers, with lots of trig --- Malmo/src/MissionSpec.cpp | 14 ++ .../NearbyCraftCommandsImplementation.java | 183 ++++++++++++++++++ .../NearbySmeltCommandsImplementation.java | 181 +++++++++++++++++ .../RewardForSmeltingItemImplementation.java | 4 +- Schemas/Mission.xsd | 2 + Schemas/Mission.xsd.in | 2 + Schemas/MissionHandlers.xsd | 54 ++++++ Schemas/MissionHandlers.xsd.in | 54 ++++++ 8 files changed, 493 insertions(+), 1 deletion(-) create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java diff --git a/Malmo/src/MissionSpec.cpp b/Malmo/src/MissionSpec.cpp index 89270e4a7..ca56c3212 100755 --- a/Malmo/src/MissionSpec.cpp +++ b/Malmo/src/MissionSpec.cpp @@ -110,6 +110,7 @@ namespace malmo child.erase("FlatWorldGenerator"); child.erase("FileWorldGenerator"); child.erase("DefaultWorldGenerator"); + child.erase("BiomeGenerator"); } } @@ -137,6 +138,11 @@ namespace malmo if (defaultWorldGenerator) { defaultWorldGenerator.get().put(".forceReset", true); } + const auto& biomeWorldGenerator = + mission.get_child_optional("Mission.ServerSection.ServerHandlers.BiomeGenerator"); + if (biomeWorldGenerator) { + biomeWorldGenerator.get().put(".forceReset", true); + } } void MissionSpec::setTimeOfDay(int t,bool allowTimeToPass) @@ -376,6 +382,8 @@ namespace malmo child.erase("DiscreteMovementCommands"); child.erase("AbsoluteMovementCommands"); child.erase("SimpleCraftCommands"); + child.erase("NearbyCraftCommands"); + child.erase("NearbySmeltCommands"); child.erase("ChatCommands"); child.erase("MissionQuitCommands"); } @@ -522,6 +530,12 @@ namespace malmo if (e.second.get_child_optional("AgentHandlers.SimpleCraftCommands")) command_handlers.push_back("SimpleCraft"); + + if (e.second.get_child_optional("AgentHandlers.NearbyCraftCommands")) + command_handlers.push_back("NearbyCraft"); + + if (e.second.get_child_optional("AgentHandlers.NearbySmeltCommands")) + command_handlers.push_back("NearbySmelt"); if (e.second.get_child_optional("AgentHandlers.MissionQuitCommands")) command_handlers.push_back("MissionQuit"); diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java new file mode 100644 index 000000000..b777b8d6b --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java @@ -0,0 +1,183 @@ +// -------------------------------------------------------------------------------------------------- +// Copyright (c) 2016 Microsoft Corporation +// +// 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 com.microsoft.Malmo.MissionHandlers; + +import io.netty.buffer.ByteBuf; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.block.BlockWorkbench; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.ByteBufUtils; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +import com.microsoft.Malmo.MalmoMod; +import com.microsoft.Malmo.Schemas.MissionInit; +import com.microsoft.Malmo.Schemas.SimpleCraftCommand; +import com.microsoft.Malmo.Schemas.NearbyCraftCommands; +import com.microsoft.Malmo.Utils.CraftingHelper; + +/** + * @author Cayden Codel, Carnegie Mellon University + *

+ * Extends the functionality of the SimpleCraftCommands by requiring a crafting table close-by. Only handles crafting, no smelting. + */ +public class NearbyCraftCommandsImplementation extends CommandBase { + private boolean isOverriding; + private static ArrayList craftingTables; + + public static class CraftMessage implements IMessage { + String parameters; + + public CraftMessage() { + } + + public CraftMessage(String parameters) { + this.parameters = parameters; + } + + @Override + public void fromBytes(ByteBuf buf) { + this.parameters = ByteBufUtils.readUTF8String(buf); + } + + @Override + public void toBytes(ByteBuf buf) { + ByteBufUtils.writeUTF8String(buf, this.parameters); + } + } + + @SubscribeEvent + public void onBlockPlace(BlockEvent.PlaceEvent event) { + if (!event.isCanceled() && event.getPlacedBlock().getBlock() instanceof BlockWorkbench) + craftingTables.add(event.getPos()); + } + + @SubscribeEvent + public void onBlockDestroy(BlockEvent.BreakEvent event) { + if (!event.isCanceled() && event.getState().getBlock() instanceof BlockWorkbench) + for (int i = craftingTables.size() - 1; i >= 0; i--) + if (craftingTables.get(i).equals(event.getPos())) + craftingTables.remove(i); + } + + public static class CraftMessageHandler implements IMessageHandler { + @Override + public IMessage onMessage(CraftMessage message, MessageContext ctx) { + EntityPlayerMP player = ctx.getServerHandler().playerEntity; + Vec3d headPos = new Vec3d(player.posX, player.posY + 1.6, player.posZ); + + // Location checking + boolean closeTable = false; + for (BlockPos furnace : craftingTables) { + Vec3d blockVec = new Vec3d(furnace.getX() + 0.5, furnace.getY() + 0.5, furnace.getZ() + 0.5); + + if (headPos.squareDistanceTo(blockVec) <= 25.0) { + // Within a reasonable FOV? + // Lots of trig, let's go + double fov = Minecraft.getMinecraft().gameSettings.fovSetting; + double height = Minecraft.getMinecraft().displayHeight; + double width = Minecraft.getMinecraft().displayWidth; + Vec3d lookVec = player.getLookVec(); + Vec3d toBlock = blockVec.subtract(headPos); + + // Projection of block onto player look vector - if greater than 0, then in front of us + double scalarProjection = lookVec.dotProduct(toBlock) / lookVec.lengthVector(); + if (scalarProjection > 0) { + Vec3d yUnit = new Vec3d(0, 1.0, 0); + Vec3d lookCross = lookVec.crossProduct(yUnit); + Vec3d blockProjectedOntoCross = lookCross.scale(lookCross.dotProduct(toBlock) / lookCross.lengthVector()); + Vec3d blockProjectedOntoPlayerPlane = toBlock.subtract(blockProjectedOntoCross); + double xyDot = lookVec.dotProduct(blockProjectedOntoPlayerPlane); + double pitchTheta = Math.acos(xyDot / (lookVec.lengthVector() * blockProjectedOntoPlayerPlane.lengthVector())); + + Vec3d playerY = lookCross.crossProduct(lookVec); + Vec3d blockProjectedOntoPlayerY = playerY.scale(playerY.dotProduct(toBlock) / playerY.lengthVector()); + Vec3d blockProjectedOntoYawPlane = toBlock.subtract(blockProjectedOntoPlayerY); + double xzDot = lookVec.dotProduct(blockProjectedOntoYawPlane); + double yawTheta = Math.acos(xzDot / (lookVec.lengthVector() * blockProjectedOntoYawPlane.lengthVector())); + + if (Math.abs(Math.toDegrees(yawTheta)) <= Math.min(1, width / height) * (fov / 2.0) && Math.abs(Math.toDegrees(pitchTheta)) <= Math.min(1, height / width) * (fov / 2.0)) + closeTable = true; + } + } + } + + if (closeTable) { + // We are close enough, try crafting recipes + List matching_recipes = CraftingHelper.getRecipesForRequestedOutput(message.parameters); + for (IRecipe recipe : matching_recipes) + if (CraftingHelper.attemptCrafting(player, recipe)) + return null; + } + + return null; + } + } + + @Override + protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { + if (verb.equalsIgnoreCase(SimpleCraftCommand.CRAFT.value())) { + MalmoMod.network.sendToServer(new CraftMessage(parameter)); + return true; + } + return false; + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof NearbyCraftCommands)) + return false; + + craftingTables = new ArrayList(); + + NearbyCraftCommands cParams = (NearbyCraftCommands) params; + setUpAllowAndDenyLists(cParams.getModifierList()); + return true; + } + + @Override + public void install(MissionInit missionInit) { + CraftingHelper.reset(); + } + + @Override + public void deinstall(MissionInit missionInit) { + } + + @Override + public boolean isOverriding() { + return this.isOverriding; + } + + @Override + public void setOverriding(boolean b) { + this.isOverriding = b; + } +} diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java new file mode 100644 index 000000000..1c6aa2e0e --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java @@ -0,0 +1,181 @@ +// -------------------------------------------------------------------------------------------------- +// Copyright (c) 2016 Microsoft Corporation +// +// 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 com.microsoft.Malmo.MissionHandlers; + +import io.netty.buffer.ByteBuf; + +import java.util.ArrayList; + +import net.minecraft.block.BlockFurnace; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.ByteBufUtils; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +import com.microsoft.Malmo.MalmoMod; +import com.microsoft.Malmo.Schemas.MissionInit; +import com.microsoft.Malmo.Schemas.SimpleCraftCommand; +import com.microsoft.Malmo.Schemas.NearbyCraftCommands; +import com.microsoft.Malmo.Utils.CraftingHelper; + +/** + * @author Cayden Codel, Carnegie Mellon University + *

+ * Extends the functionality of the SimpleCraftCommands by requiring a furnace close-by. Only handles smelting, no crafting. + */ +public class NearbySmeltCommandsImplementation extends CommandBase { + private boolean isOverriding; + private static ArrayList furnaces; + + public static class CraftMessage implements IMessage { + String parameters; + + public CraftMessage() { + } + + public CraftMessage(String parameters) { + this.parameters = parameters; + } + + @Override + public void fromBytes(ByteBuf buf) { + this.parameters = ByteBufUtils.readUTF8String(buf); + } + + @Override + public void toBytes(ByteBuf buf) { + ByteBufUtils.writeUTF8String(buf, this.parameters); + } + } + + @SubscribeEvent + public void onBlockPlace(BlockEvent.PlaceEvent event) { + if (!event.isCanceled() && event.getPlacedBlock().getBlock() instanceof BlockFurnace) + furnaces.add(event.getPos()); + } + + @SubscribeEvent + public void onBlockDestroy(BlockEvent.BreakEvent event) { + if (!event.isCanceled() && event.getState().getBlock() instanceof BlockFurnace) + for (int i = furnaces.size() - 1; i >= 0; i--) + if (furnaces.get(i).equals(event.getPos())) + furnaces.remove(i); + } + + public static class CraftMessageHandler implements IMessageHandler { + @Override + public IMessage onMessage(CraftMessage message, MessageContext ctx) { + EntityPlayerMP player = ctx.getServerHandler().playerEntity; + Vec3d headPos = new Vec3d(player.posX, player.posY + 1.6, player.posZ); + + // Location checking + boolean closeFurnace = false; + for (BlockPos furnace : furnaces) { + Vec3d blockVec = new Vec3d(furnace.getX() + 0.5, furnace.getY() + 0.5, furnace.getZ() + 0.5); + + if (headPos.squareDistanceTo(blockVec) <= 25.0) { + // Within a reasonable FOV? + // Lots of trig, let's go + double fov = Minecraft.getMinecraft().gameSettings.fovSetting; + double height = Minecraft.getMinecraft().displayHeight; + double width = Minecraft.getMinecraft().displayWidth; + Vec3d lookVec = player.getLookVec(); + Vec3d toBlock = blockVec.subtract(headPos); + + // Projection of block onto player look vector - if greater than 0, then in front of us + double scalarProjection = lookVec.dotProduct(toBlock) / lookVec.lengthVector(); + if (scalarProjection > 0) { + Vec3d yUnit = new Vec3d(0, 1.0, 0); + Vec3d lookCross = lookVec.crossProduct(yUnit); + Vec3d blockProjectedOntoCross = lookCross.scale(lookCross.dotProduct(toBlock) / lookCross.lengthVector()); + Vec3d blockProjectedOntoPlayerPlane = toBlock.subtract(blockProjectedOntoCross); + double xyDot = lookVec.dotProduct(blockProjectedOntoPlayerPlane); + double pitchTheta = Math.acos(xyDot / (lookVec.lengthVector() * blockProjectedOntoPlayerPlane.lengthVector())); + + Vec3d playerY = lookCross.crossProduct(lookVec); + Vec3d blockProjectedOntoPlayerY = playerY.scale(playerY.dotProduct(toBlock) / playerY.lengthVector()); + Vec3d blockProjectedOntoYawPlane = toBlock.subtract(blockProjectedOntoPlayerY); + double xzDot = lookVec.dotProduct(blockProjectedOntoYawPlane); + double yawTheta = Math.acos(xzDot / (lookVec.lengthVector() * blockProjectedOntoYawPlane.lengthVector())); + + if (Math.abs(Math.toDegrees(yawTheta)) <= Math.min(1, width / height) * (fov / 2.0) && Math.abs(Math.toDegrees(pitchTheta)) <= Math.min(1, height / width) * (fov / 2.0)) + closeFurnace = true; + } + } + } + + if (closeFurnace) { + ItemStack input = CraftingHelper.getSmeltingRecipeForRequestedOutput(message.parameters); + if (input != null) + if (CraftingHelper.attemptSmelting(player, input)) + return null; + } + + return null; + } + } + + @Override + protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { + if (verb.equalsIgnoreCase(SimpleCraftCommand.CRAFT.value())) { + MalmoMod.network.sendToServer(new CraftMessage(parameter)); + return true; + } + return false; + } + + @Override + public boolean parseParameters(Object params) { + furnaces = new ArrayList(); + + if (!(params instanceof NearbyCraftCommands)) + return false; + + NearbyCraftCommands cParams = (NearbyCraftCommands) params; + setUpAllowAndDenyLists(cParams.getModifierList()); + return true; + } + + @Override + public void install(MissionInit missionInit) { + CraftingHelper.reset(); + } + + @Override + public void deinstall(MissionInit missionInit) { + } + + @Override + public boolean isOverriding() { + return this.isOverriding; + } + + @Override + public void setOverriding(boolean b) { + this.isOverriding = b; + } +} \ No newline at end of file diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java index 9eee04e9b..9f3ccc761 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/RewardForSmeltingItemImplementation.java @@ -82,19 +82,21 @@ private void addSmeltedItemCount(ItemStack is) { } private void checkForMatch(ItemStack is) { + System.out.println("[REWARD] Checking stack " + is.getUnlocalizedName() + " " + is.getCount()); int savedSmelted = getSmeltedItemCount(is); + System.out.println("[REWARD] Previous saved amount is " + savedSmelted); for (ItemMatcher matcher : this.matchers) { if (matcher.matches(is)) { if (!params.isSparse()) { if (savedSmelted != 0 && savedSmelted < matcher.matchSpec.getAmount()) { for (int i = savedSmelted; i < matcher.matchSpec.getAmount() && i - savedSmelted < is.getCount(); i++) { + System.out.println("Giving reward"); this.adjustAndDistributeReward( ((BlockOrItemSpecWithReward) matcher.matchSpec).getReward().floatValue(), params.getDimension(), ((BlockOrItemSpecWithReward) matcher.matchSpec).getDistribution()); } - } else if (savedSmelted != 0 && savedSmelted >= matcher.matchSpec.getAmount()) { // Do nothing } else { diff --git a/Schemas/Mission.xsd b/Schemas/Mission.xsd index 6fe39f44c..d4a5346db 100644 --- a/Schemas/Mission.xsd +++ b/Schemas/Mission.xsd @@ -371,6 +371,8 @@ + + diff --git a/Schemas/Mission.xsd.in b/Schemas/Mission.xsd.in index d9a7be0f9..63ea05613 100644 --- a/Schemas/Mission.xsd.in +++ b/Schemas/Mission.xsd.in @@ -371,6 +371,8 @@ + + diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd index 5390b4141..b82bfe4f8 100644 --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -1687,6 +1687,60 @@ + + + + + When present, the Mod will accept simple commands that implement a basic form of crafting. Success of the craft command depends on the presence of a nearby crafting table previously placed by the agent and within reach and in field of view. + + + + + + + + + + + + + + + + + + + + + + + + When present, the Mod will accept simple commands that implement a basic form of smelting. Success of the smelt command depends on the presence of a nearby furnace previously placed by the agent and within reach and in field of view. Fails when a command corresponds to an item not able to be smelted. Each command takes fuel as if the agent had placed the items in a furnace. + + Eg: + + If called on 16 iron ore, requires 2 coal, 2 charcoal, 11 planks, etc. + + If called twice separately on 8 iron ore, requires 1 coal and then 1 coal, etc. + + + + + + + + + + + + + + + + + + + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index eda5db440..21c67a619 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -1685,6 +1685,60 @@ + + + + + When present, the Mod will accept simple commands that implement a basic form of crafting. Success of the craft command depends on the presence of a nearby crafting table previously placed by the agent and within reach and in field of view. + + + + + + + + + + + + + + + + + + + + + + + + When present, the Mod will accept simple commands that implement a basic form of smelting. Success of the smelt command depends on the presence of a nearby furnace previously placed by the agent and within reach and in field of view. Fails when a command corresponds to an item not able to be smelted. Each command takes fuel as if the agent had placed the items in a furnace. + + Eg: + + If called on 16 iron ore, requires 2 coal, 2 charcoal, 11 planks, etc. + + If called twice separately on 8 iron ore, requires 1 coal and then 1 coal, etc. + + + + + + + + + + + + + + + + + + + From 353bf5c1a2cbb6fde58fe941bf6911a0312aa762 Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Thu, 21 Feb 2019 22:22:41 -0500 Subject: [PATCH 22/40] Merged version changes --- Minecraft/src/main/resources/schemas.index | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Minecraft/src/main/resources/schemas.index b/Minecraft/src/main/resources/schemas.index index 70b4a99d8..55dcedb71 100644 --- a/Minecraft/src/main/resources/schemas.index +++ b/Minecraft/src/main/resources/schemas.index @@ -1,5 +1,5 @@ -Mission.xsd -MissionEnded.xsd MissionHandlers.xsd MissionInit.xsd +MissionEnded.xsd Types.xsd +Mission.xsd From 222c0844194409c7ff8c000bf27b1fab7e319bdb Mon Sep 17 00:00:00 2001 From: ccodel Date: Tue, 19 Feb 2019 19:10:39 -0500 Subject: [PATCH 23/40] Added place commands, not yet tested --- CMakeLists.txt | 16 +- Malmo/src/MissionSpec.cpp | 9 + Malmo/src/MissionSpec.h | 4 + ...tQuitFromPossessingItemImplementation.java | 322 +++++++++--------- .../PlaceCommandsImplementation.java | 132 +++++++ Schemas/MissionHandlers.xsd | 51 ++- Schemas/MissionHandlers.xsd.in | 48 +++ 7 files changed, 413 insertions(+), 169 deletions(-) create mode 100644 Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java diff --git a/CMakeLists.txt b/CMakeLists.txt index f3bdd4165..d8fb4e997 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,9 +51,10 @@ set( STATIC_BOOST ON CACHE BOOL ${STATIC_BOOST_DESC} ) if( INCLUDE_PYTHON ) set( USE_PYTHON_VERSIONS_DESC "Specifies which version of Python to build Malmo with Python bindings" ) + set( MACOS_USE_PYTHON_MODULE_DESC "Specifies which Python module to build Malmo on Apple MacOS" ) set( USE_PYTHON_VERSIONS 3.6 CACHE STRING ${USE_PYTHON_VERSIONS_DESC} ) - set( BOOST_PYTHON_NAME_DESC "Specifies which Boost Python module to build Malmo with" ) - set( BOOST_PYTHON_NAME "python3" CACHE STRING ${BOOST_PYTHON_NAME_DESC} ) + # Boost has switched to using a 2 digit naming convention for python on MacOS. + set( MACOS_USE_PYTHON_MODULE "python37" CACHE STRING ${MACOS_USE_PYTHON_MODULE_DESC} ) endif() set( WARNINGS_AS_ERRORS OFF ) @@ -105,18 +106,21 @@ SET(Boost_ADDITIONAL_VERSIONS "1.67" "1.67.0") SET(BOOST_PYTHON_MODULE_NAME "python") if ( USE_PYTHON_VERSIONS VERSION_GREATER 3 ) - SET( BOOST_PYTHON_MODULE_NAME ${BOOST_PYTHON_NAME} ) + if ( APPLE ) + SET( BOOST_PYTHON_MODULE_NAME ${MACOS_USE_PYTHON_MODULE} ) + else() + SET( BOOST_PYTHON_MODULE_NAME "python3" ) + endif() endif() if( WIN32 ) SET(Boost_USE_STATIC_LIBS ON) - find_package( Boost COMPONENTS chrono date_time filesystem iostreams program_options ${BOOST_PYTHON_MODULE_NAME} regex system thread REQUIRED ) - add_definitions(-DBOOST_ALL_NO_LIB=1) # Turn off auto-linking, creates problems when linking boost statically + find_package( Boost COMPONENTS chrono date_time filesystem iostreams program_options ${BOOST_PYTHON_MODULE_NAME} regex system thread zlib REQUIRED ) else() - SET(Boost_USE_STATIC_LIBS ${STATIC_BOOST}) find_package( Boost COMPONENTS chrono date_time filesystem iostreams program_options ${BOOST_PYTHON_MODULE_NAME} regex system thread REQUIRED ) set(CMAKE_THREAD_PREFER_PTHREAD TRUE) find_package( Threads REQUIRED ) + SET(Boost_USE_STATIC_LIBS ${STATIC_BOOST}) endif() # suggested install paths - see readme.md diff --git a/Malmo/src/MissionSpec.cpp b/Malmo/src/MissionSpec.cpp index ca56c3212..a274b42b7 100755 --- a/Malmo/src/MissionSpec.cpp +++ b/Malmo/src/MissionSpec.cpp @@ -384,6 +384,7 @@ namespace malmo child.erase("SimpleCraftCommands"); child.erase("NearbyCraftCommands"); child.erase("NearbySmeltCommands"); + child.erase("PlaceCommands"); child.erase("ChatCommands"); child.erase("MissionQuitCommands"); } @@ -433,6 +434,11 @@ namespace malmo { mission.put("Mission.AgentSection.AgentHandlers.ChatCommands", ""); } + + void MissionSpec::allowAllPlaceCommands() + { + mission.put("Mission.AgentSection.AgentHandlers.PlaceCommands", ""); + } // ------------------------------- information --------------------------------------------------- @@ -536,6 +542,9 @@ namespace malmo if (e.second.get_child_optional("AgentHandlers.NearbySmeltCommands")) command_handlers.push_back("NearbySmelt"); + + if (e.second.get_child_optional("AgentHandlers.PlaceCommands")) + command_handlers.push_back("Place"); if (e.second.get_child_optional("AgentHandlers.MissionQuitCommands")) command_handlers.push_back("MissionQuit"); diff --git a/Malmo/src/MissionSpec.h b/Malmo/src/MissionSpec.h index 5804f0b0e..c5f644927 100755 --- a/Malmo/src/MissionSpec.h +++ b/Malmo/src/MissionSpec.h @@ -299,6 +299,10 @@ namespace malmo //! Only applies to the first agent in the mission. For multi-agent missions, specify the command handlers for each in the XML. void allowAllChatCommands(); + //! Adds a place command handler if none present, with neither an allow-list or a deny-list, thus allowing any command to be sent. + //! Only applies to the first agent in the mission. For multi-agent missions, specify the command handlers for each in the XML. + void allowAllPlaceCommands(); + // ------------------------- information -------------------------------------- //! Returns the short description of the mission. diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java index 1629cf061..717164a33 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromPossessingItemImplementation.java @@ -28,165 +28,165 @@ */ public class AgentQuitFromPossessingItemImplementation extends HandlerBase implements IWantToQuit { - private AgentQuitFromPossessingItem params; - private HashMap collectedItems; - private List matchers; - private String quitCode = ""; - private boolean wantToQuit = false; - - public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { - String description; - - ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { - super(spec); - this.description = spec.getDescription(); - } - - String description() { - return this.description; - } - } - - @Override - public boolean parseParameters(Object params) { - if (!(params instanceof AgentQuitFromPossessingItem)) - return false; - - this.params = (AgentQuitFromPossessingItem) params; - this.matchers = new ArrayList(); - for (BlockOrItemSpecWithDescription bs : this.params.getItem()) - this.matchers.add(new ItemQuitMatcher(bs)); - return true; - } - - @Override - public boolean doIWantToQuit(MissionInit missionInit) { - return this.wantToQuit; - } - - @Override - public String getOutcome() { - return this.quitCode; - } - - @Override - public void prepare(MissionInit missionInit) { - MinecraftForge.EVENT_BUS.register(this); - collectedItems = new HashMap(); - } - - @Override - public void cleanup() { - MinecraftForge.EVENT_BUS.unregister(this); - } - - @SubscribeEvent - public void onGainItem(GainItemEvent event) { - checkForMatch(event.stack); - } - - @SubscribeEvent - public void onPickupItem(EntityItemPickupEvent event) { - if (event.getItem() != null) - checkForMatch(event.getItem().getEntityItem()); - } - - @SubscribeEvent - public void onLoseItem(LoseItemEvent event) { - if (event.stack != null) - removeCollectedItemCount(event.stack); - } - - @SubscribeEvent - public void onDropItem(ItemTossEvent event) { - removeCollectedItemCount(event.getEntityItem().getEntityItem()); - } - - @SubscribeEvent - public void onDestroyItem(PlayerDestroyItemEvent event) { - removeCollectedItemCount(event.getOriginal()); - } - - @SubscribeEvent - public void onBlockPlace(PlaceEvent event) { - if (!event.isCanceled() && event.getPlacedBlock() != null) { - ItemStack stack = new ItemStack(event.getPlacedBlock().getBlock()); - removeCollectedItemCount(stack); - } - } - - /** - * Checks whether the ItemStack matches a variant stored in the item list. If - * so, returns true, else returns false. - * - * @param is The item stack - * @return If the stack is allowed in the item matchers and has color or - * variants enabled, returns true, else false. - */ - private boolean getVariant(ItemStack is) { - for (ItemQuitMatcher matcher : matchers) { - if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { - if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) - return true; - if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) - return true; - } - } - - return false; - } - - private void addCollectedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getUnlocalizedName())); - if (variant) - collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); - else - collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); - - } - - private void removeCollectedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 - : collectedItems.get(is.getUnlocalizedName())); - if (variant) - collectedItems.put(is.getUnlocalizedName(), prev - is.getCount()); - else - collectedItems.put(is.getItem().getUnlocalizedName(), prev - is.getCount()); - } - - private int getCollectedItemCount(ItemStack is) { - boolean variant = getVariant(is); - - if (variant) - return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 : collectedItems.get(is.getUnlocalizedName()); - else - return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 - : collectedItems.get(is.getItem().getUnlocalizedName()); - } - - private void checkForMatch(ItemStack is) { - int savedCollected = getCollectedItemCount(is); - if (is != null) { - for (ItemQuitMatcher matcher : this.matchers) { - if (matcher.matches(is)) { - if (savedCollected != 0) { - if (is.getCount() + savedCollected >= matcher.matchSpec.getAmount()) { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } else if (is.getCount() >= matcher.matchSpec.getAmount()) { - this.quitCode = matcher.description(); - this.wantToQuit = true; - } - } - } - - addCollectedItemCount(is); - } - } + private AgentQuitFromPossessingItem params; + private HashMap collectedItems; + private List matchers; + private String quitCode = ""; + private boolean wantToQuit = false; + + public static class ItemQuitMatcher extends RewardForItemBase.ItemMatcher { + String description; + + ItemQuitMatcher(BlockOrItemSpecWithDescription spec) { + super(spec); + this.description = spec.getDescription(); + } + + String description() { + return this.description; + } + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof AgentQuitFromPossessingItem)) + return false; + + this.params = (AgentQuitFromPossessingItem) params; + this.matchers = new ArrayList(); + for (BlockOrItemSpecWithDescription bs : this.params.getItem()) + this.matchers.add(new ItemQuitMatcher(bs)); + return true; + } + + @Override + public boolean doIWantToQuit(MissionInit missionInit) { + return this.wantToQuit; + } + + @Override + public String getOutcome() { + return this.quitCode; + } + + @Override + public void prepare(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.register(this); + collectedItems = new HashMap(); + } + + @Override + public void cleanup() { + MinecraftForge.EVENT_BUS.unregister(this); + } + + @SubscribeEvent + public void onGainItem(GainItemEvent event) { + checkForMatch(event.stack); + } + + @SubscribeEvent + public void onPickupItem(EntityItemPickupEvent event) { + if (event.getItem() != null) + checkForMatch(event.getItem().getEntityItem()); + } + + @SubscribeEvent + public void onLoseItem(LoseItemEvent event) { + if (event.stack != null) + removeCollectedItemCount(event.stack); + } + + @SubscribeEvent + public void onDropItem(ItemTossEvent event) { + removeCollectedItemCount(event.getEntityItem().getEntityItem()); + } + + @SubscribeEvent + public void onDestroyItem(PlayerDestroyItemEvent event) { + removeCollectedItemCount(event.getOriginal()); + } + + @SubscribeEvent + public void onBlockPlace(PlaceEvent event) { + if (!event.isCanceled() && event.getPlacedBlock() != null) { + ItemStack stack = new ItemStack(event.getPlacedBlock().getBlock()); + removeCollectedItemCount(stack); + } + } + + /** + * Checks whether the ItemStack matches a variant stored in the item list. If + * so, returns true, else returns false. + * + * @param is The item stack + * @return If the stack is allowed in the item matchers and has color or + * variants enabled, returns true, else false. + */ + private boolean getVariant(ItemStack is) { + for (ItemQuitMatcher matcher : matchers) { + if (matcher.allowedItemTypes.contains(is.getItem().getUnlocalizedName())) { + if (matcher.matchSpec.getColour() != null && matcher.matchSpec.getColour().size() > 0) + return true; + if (matcher.matchSpec.getVariant() != null && matcher.matchSpec.getVariant().size() > 0) + return true; + } + } + + return false; + } + + private void addCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + if (variant) + collectedItems.put(is.getUnlocalizedName(), prev + is.getCount()); + else + collectedItems.put(is.getItem().getUnlocalizedName(), prev + is.getCount()); + + } + + private void removeCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + int prev = (collectedItems.get(is.getUnlocalizedName()) == null ? 0 + : collectedItems.get(is.getUnlocalizedName())); + if (variant) + collectedItems.put(is.getUnlocalizedName(), prev - is.getCount()); + else + collectedItems.put(is.getItem().getUnlocalizedName(), prev - is.getCount()); + } + + private int getCollectedItemCount(ItemStack is) { + boolean variant = getVariant(is); + + if (variant) + return (collectedItems.get(is.getUnlocalizedName()) == null) ? 0 : collectedItems.get(is.getUnlocalizedName()); + else + return (collectedItems.get(is.getItem().getUnlocalizedName()) == null) ? 0 + : collectedItems.get(is.getItem().getUnlocalizedName()); + } + + private void checkForMatch(ItemStack is) { + int savedCollected = getCollectedItemCount(is); + if (is != null) { + for (ItemQuitMatcher matcher : this.matchers) { + if (matcher.matches(is)) { + if (savedCollected != 0) { + if (is.getCount() + savedCollected >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } else if (is.getCount() >= matcher.matchSpec.getAmount()) { + this.quitCode = matcher.description(); + this.wantToQuit = true; + } + } + } + + addCollectedItemCount(is); + } + } } \ No newline at end of file diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java new file mode 100644 index 000000000..470bc607f --- /dev/null +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java @@ -0,0 +1,132 @@ +// -------------------------------------------------------------------------------------------------- +// Copyright (c) 2016 Microsoft Corporation +// +// 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 com.microsoft.Malmo.MissionHandlers; + +import com.microsoft.Malmo.Schemas.*; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; + +import com.microsoft.Malmo.MissionHandlerInterfaces.ICommandHandler; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraftforge.common.util.BlockSnapshot; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.common.MinecraftForge; + +/** + * @author Cayden Codel, Carnegie Mellon University + *

+ * Place commands allow agents to place blocks in the world without having to worry about inventory management. + */ +public class PlaceCommandsImplementation extends CommandBase implements ICommandHandler { + private boolean isOverriding; + + @Override + protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { + EntityPlayerSP player = Minecraft.getMinecraft().player; + if (player == null) + return false; + + if (!verb.equalsIgnoreCase(PlaceCommand.PLACE.value())) + return false; + + InventoryPlayer inv = player.inventory; + Block b = Block.getBlockFromName(parameter); + if (b == null || b.getRegistryName() == null) + return false; + + boolean foundBlock = false; + for (int i = 0; i < 41 && !foundBlock; i++) { + ItemStack s = inv.getStackInSlot(i).copy(); + if (b.getRegistryName().equals(s.getItem().getRegistryName())) { + int selectedHotBarItem = inv.currentItem; + ItemStack selected = inv.getStackInSlot(selectedHotBarItem).copy(); + inv.setInventorySlotContents(selectedHotBarItem, s); + inv.setInventorySlotContents(i, selected); + + RayTraceResult mop = Minecraft.getMinecraft().objectMouseOver; + if (mop.typeOfHit == RayTraceResult.Type.BLOCK) { + BlockPos pos = mop.getBlockPos().add(mop.sideHit.getDirectionVec()); + // Can we place this block here? + AxisAlignedBB axisalignedbb = b.getDefaultState().getCollisionBoundingBox(player.world, pos); + if (axisalignedbb == null) { + PlayerInteractEvent event = new PlayerInteractEvent.RightClickBlock(player, EnumHand.MAIN_HAND, mop.getBlockPos(), mop.sideHit, mop.hitVec); + MinecraftForge.EVENT_BUS.post(event); + if (!event.isCanceled()) { + BlockPos newPos = mop.getBlockPos().add(mop.sideHit.getDirectionVec()); + Block newB = Block.getBlockFromItem(inv.getCurrentItem().getItem()); + IBlockState blockType = newB.getStateFromMeta(inv.getCurrentItem().getMetadata()); + if (player.world.setBlockState(newPos, blockType)) { + BlockSnapshot snapshot = new BlockSnapshot(player.world, newPos, blockType); + BlockEvent.PlaceEvent placeEvent = new BlockEvent.PlaceEvent(snapshot, player.world.getBlockState(mop.getBlockPos()), player, EnumHand.MAIN_HAND); + MinecraftForge.EVENT_BUS.post(placeEvent); + // We set the block, so remove it from the inventory. + if (!player.isCreative()) { + if (player.inventory.getCurrentItem().getCount() > 1) + player.inventory.getCurrentItem().setCount(player.inventory.getCurrentItem().getCount() - 1); + else + player.inventory.mainInventory.get(player.inventory.currentItem).setCount(0); + } + } + } + } + } + foundBlock = true; + } + } + + return true; + } + + @Override + public boolean parseParameters(Object params) { + if (!(params instanceof PlaceCommands)) + return false; + + PlaceCommands pParams = (PlaceCommands) params; + setUpAllowAndDenyLists(pParams.getModifierList()); + return true; + } + + @Override + public void install(MissionInit missionInit) { + } + + @Override + public void deinstall(MissionInit missionInit) { + } + + @Override + public boolean isOverriding() { + return this.isOverriding; + } + + @Override + public void setOverriding(boolean b) { + this.isOverriding = b; + } +} \ No newline at end of file diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd index b82bfe4f8..52d78a55a 100644 --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -1066,9 +1066,7 @@ Sets whether or not the compass location should be randomized within a certain radius. - If false, will set the compass location to the block that was randomly placed. - If true, will set the compass location to a random spot within the radius specified below. @@ -1464,6 +1462,27 @@ + + + + + A command for placing blocks in the agent's inventory: + + Will look in the agent's inventory. If the block exists, will try to place the block in the world. + + For basic objects, use BlockTypes found in Types.xsd. Eg: + + "{{{place diamond_block}}}" will attempt to place a diamond block from the agent's inventory. + + for more control over colours, types, etc, add a Variation or Colour. Eg: + + "{{{place carpet PINK}}}" + + + + + + @@ -1741,6 +1760,33 @@ + + + + + When present, the Mod will accept commands that allow for the placement of blocks. If the specified block is contained in the agent's inventory, then the agent will attempt to place the block in the world. + + If a non-block is specified, the command fails. + + If a block is specified, the block will swap to the hotbar, be placed, and then swapped back, so no changes to the inventory are made besides losing a block. + + + + + + + + + + + + + + + + + + @@ -2110,6 +2156,7 @@ + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index 21c67a619..c3359a536 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -1462,6 +1462,27 @@ + + + + + A command for placing blocks in the agent's inventory: + + Will look in the agent's inventory. If the block exists, will try to place the block in the world. + + For basic objects, use BlockTypes found in Types.xsd. Eg: + + "{{{place diamond_block}}}" will attempt to place a diamond block from the agent's inventory. + + for more control over colours, types, etc, add a Variation or Colour. Eg: + + "{{{place carpet PINK}}}" + + + + + + @@ -1739,6 +1760,33 @@ + + + + + When present, the Mod will accept commands that allow for the placement of blocks. If the specified block is contained in the agent's inventory, then the agent will attempt to place the block in the world. + + If a non-block is specified, the command fails. + + If a block is specified, the block will swap to the hotbar, be placed, and then swapped back, so no changes to the inventory are made besides losing a block. + + + + + + + + + + + + + + + + + + From a394b7f1611e7e774e70e323c14d1158c8b6412b Mon Sep 17 00:00:00 2001 From: ccodel Date: Tue, 19 Feb 2019 19:14:09 -0500 Subject: [PATCH 24/40] Swapped items back --- .../Malmo/MissionHandlers/PlaceCommandsImplementation.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java index 470bc607f..3cb3bfe6a 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java @@ -66,7 +66,6 @@ protected boolean onExecute(String verb, String parameter, MissionInit missionIn int selectedHotBarItem = inv.currentItem; ItemStack selected = inv.getStackInSlot(selectedHotBarItem).copy(); inv.setInventorySlotContents(selectedHotBarItem, s); - inv.setInventorySlotContents(i, selected); RayTraceResult mop = Minecraft.getMinecraft().objectMouseOver; if (mop.typeOfHit == RayTraceResult.Type.BLOCK) { @@ -96,6 +95,9 @@ protected boolean onExecute(String verb, String parameter, MissionInit missionIn } } foundBlock = true; + + inv.setInventorySlotContents(i, inv.getCurrentItem()); + inv.setInventorySlotContents(selectedHotBarItem, selected); } } From 6da0907cf074f510bdaa6e36923e9c3bdf32993a Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Thu, 21 Feb 2019 22:18:42 -0500 Subject: [PATCH 25/40] Updated commands for cayden's new handlers --- Malmo/samples/samples.iml | 22 +++++++++ Malmo/src/MissionSpec.cpp | 4 +- .../java/com/microsoft/Malmo/MalmoMod.java | 5 +++ .../NearbyCraftCommandsImplementation.java | 4 +- .../NearbySmeltCommandsImplementation.java | 10 ++--- Minecraft/src/main/resources/schemas.index | 4 +- Schemas/MissionHandlers.xsd | 40 +++++++++++++---- Schemas/MissionHandlers.xsd.in | 45 ++++++++++++++++--- Schemas/Schemas.iml | 9 ++++ 9 files changed, 116 insertions(+), 27 deletions(-) create mode 100644 Malmo/samples/samples.iml create mode 100644 Schemas/Schemas.iml diff --git a/Malmo/samples/samples.iml b/Malmo/samples/samples.iml new file mode 100644 index 000000000..722c9789b --- /dev/null +++ b/Malmo/samples/samples.iml @@ -0,0 +1,22 @@ + + + + + + + MIXIN + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Malmo/src/MissionSpec.cpp b/Malmo/src/MissionSpec.cpp index a274b42b7..8791244f5 100755 --- a/Malmo/src/MissionSpec.cpp +++ b/Malmo/src/MissionSpec.cpp @@ -382,8 +382,8 @@ namespace malmo child.erase("DiscreteMovementCommands"); child.erase("AbsoluteMovementCommands"); child.erase("SimpleCraftCommands"); - child.erase("NearbyCraftCommands"); - child.erase("NearbySmeltCommands"); + child.erase("SimpleCraftCraftCommands"); + child.erase("SimpleSmeltCommands"); child.erase("PlaceCommands"); child.erase("ChatCommands"); child.erase("MissionQuitCommands"); diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java b/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java index 65c076a2a..4c8b189d5 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java @@ -32,6 +32,7 @@ import java.util.Map; import java.util.Map.Entry; +import main.java.com.microsoft.Malmo.MissionHandlers.SimpleCraftNearbyCommandsImplementation; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; @@ -65,6 +66,8 @@ import com.microsoft.Malmo.MissionHandlers.ObservationFromGridImplementation; import com.microsoft.Malmo.MissionHandlers.ObservationFromSystemImplementation; import com.microsoft.Malmo.MissionHandlers.SimpleCraftCommandsImplementation; +import com.microsoft.Malmo.MissionHandlers.NearbyCraftCommandsImplementation; +import com.microsoft.Malmo.MissionHandlers.NearbySmeltCommandsImplementation; import com.microsoft.Malmo.Schemas.MissionInit; import com.microsoft.Malmo.Server.MalmoModServer; import com.microsoft.Malmo.Utils.AddressHelper; @@ -134,6 +137,8 @@ public void preInit(FMLPreInitializationEvent event) network.registerMessage(ObservationFromGridImplementation.GridRequestMessageHandler.class, ObservationFromGridImplementation.GridRequestMessage.class, 2, Side.SERVER); network.registerMessage(MalmoMessageHandler.class, MalmoMessage.class, 3, Side.CLIENT); // Malmo messages from server to client network.registerMessage(SimpleCraftCommandsImplementation.CraftMessageHandler.class, SimpleCraftCommandsImplementation.CraftMessage.class, 4, Side.SERVER); + network.registerMessage(NearbyCraftCommandsImplementation.CraftMessageHandler.class, NearbyCraftCommandsImplementation.CraftMessage.class, 4, Side.SERVER); + network.registerMessage(NearbySmeltCommandsImplementation.CraftMessageHandler.class, NearbySmeltCommandsImplementation.CraftMessage.class, 4, Side.SERVER); network.registerMessage(AbsoluteMovementCommandsImplementation.TeleportMessageHandler.class, AbsoluteMovementCommandsImplementation.TeleportMessage.class, 5, Side.SERVER); network.registerMessage(MalmoMessageHandler.class, MalmoMessage.class, 6, Side.SERVER); // Malmo messages from client to server network.registerMessage(InventoryCommandsImplementation.InventoryMessageHandler.class, InventoryCommandsImplementation.InventoryMessage.class, 7, Side.SERVER); diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java index b777b8d6b..00569f912 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java @@ -39,7 +39,7 @@ import com.microsoft.Malmo.MalmoMod; import com.microsoft.Malmo.Schemas.MissionInit; -import com.microsoft.Malmo.Schemas.SimpleCraftCommand; +import com.microsoft.Malmo.Schemas.NearbyCraftCommand; import com.microsoft.Malmo.Schemas.NearbyCraftCommands; import com.microsoft.Malmo.Utils.CraftingHelper; @@ -143,7 +143,7 @@ public IMessage onMessage(CraftMessage message, MessageContext ctx) { @Override protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { - if (verb.equalsIgnoreCase(SimpleCraftCommand.CRAFT.value())) { + if (verb.equalsIgnoreCase(NearbyCraftCommand.CRAFT.value())) { MalmoMod.network.sendToServer(new CraftMessage(parameter)); return true; } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java index 1c6aa2e0e..263617e53 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java @@ -38,8 +38,8 @@ import com.microsoft.Malmo.MalmoMod; import com.microsoft.Malmo.Schemas.MissionInit; -import com.microsoft.Malmo.Schemas.SimpleCraftCommand; -import com.microsoft.Malmo.Schemas.NearbyCraftCommands; +import com.microsoft.Malmo.Schemas.NearbySmeltCommand; +import com.microsoft.Malmo.Schemas.NearbySmeltCommands; import com.microsoft.Malmo.Utils.CraftingHelper; /** @@ -141,7 +141,7 @@ public IMessage onMessage(CraftMessage message, MessageContext ctx) { @Override protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { - if (verb.equalsIgnoreCase(SimpleCraftCommand.CRAFT.value())) { + if (verb.equalsIgnoreCase(NearbySmeltCommand.CRAFT.value())) { MalmoMod.network.sendToServer(new CraftMessage(parameter)); return true; } @@ -152,10 +152,10 @@ protected boolean onExecute(String verb, String parameter, MissionInit missionIn public boolean parseParameters(Object params) { furnaces = new ArrayList(); - if (!(params instanceof NearbyCraftCommands)) + if (!(params instanceof NearbySmeltCommands)) return false; - NearbyCraftCommands cParams = (NearbyCraftCommands) params; + NearbySmeltCommands cParams = (NearbySmeltCommands) params; setUpAllowAndDenyLists(cParams.getModifierList()); return true; } diff --git a/Minecraft/src/main/resources/schemas.index b/Minecraft/src/main/resources/schemas.index index 55dcedb71..70b4a99d8 100644 --- a/Minecraft/src/main/resources/schemas.index +++ b/Minecraft/src/main/resources/schemas.index @@ -1,5 +1,5 @@ +Mission.xsd +MissionEnded.xsd MissionHandlers.xsd MissionInit.xsd -MissionEnded.xsd Types.xsd -Mission.xsd diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd index 52d78a55a..666d596dd 100644 --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -1445,21 +1445,43 @@ A command for simple crafting: - Will look up all recipes that produce the requested object, and attempt each one in turn until one is successful or all have failed. This ignores all issues like requiring a crafting table / brewing stand etc, and the shape of the recipe (which items go in which slots on the crafting table). It will simply check to see whether the player has the necessary raw ingredients, and, if so, will remove them from the player's inventory and add the result of the recipe. + "{{{craft carpet PINK}}}" - For basic objects, use the ItemTypes or BlockTypes found in Types.xsd. Eg: + etc. + + + + + + - "{{{craft diamond_pickaxe}}}" will remove three diamonds and two sticks from the player's inventory, and add a diamond pickaxe. + + + + A command for simple nearby crafting: - For more control over colours, types etc, add a Variation or Colour. Eg: + "{{{craftNearby carpet PINK}}}" - "{{{craft carpet PINK}}}" + etc. + + + + + + + + + + + A command for simple smelting: + + "{{{smeltNearby carpet PINK}}}" etc. - + @@ -1546,7 +1568,7 @@ - + @@ -1721,7 +1743,7 @@ - + @@ -1751,7 +1773,7 @@ - + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index c3359a536..28b767452 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -1462,6 +1462,37 @@ + + + + + + A command for simple nearby crafting: + + "{{{craftNearby carpet PINK}}}" + + etc. + + + + + + + + + + + A command for simple smelting: + + "{{{smelt carpet PINK}}}" + + etc. + + + + + + @@ -1721,7 +1752,7 @@ - + @@ -1730,16 +1761,16 @@ - + When present, the Mod will accept simple commands that implement a basic form of smelting. Success of the smelt command depends on the presence of a nearby furnace previously placed by the agent and within reach and in field of view. Fails when a command corresponds to an item not able to be smelted. Each command takes fuel as if the agent had placed the items in a furnace. - + Eg: - + If called on 16 iron ore, requires 2 coal, 2 charcoal, 11 planks, etc. - + If called twice separately on 8 iron ore, requires 1 coal and then 1 coal, etc. @@ -1751,7 +1782,7 @@ - + @@ -1760,7 +1791,7 @@ - + diff --git a/Schemas/Schemas.iml b/Schemas/Schemas.iml new file mode 100644 index 000000000..8021953ed --- /dev/null +++ b/Schemas/Schemas.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file From 6c54ed2dbef52634f05eb0a65baba3e1c7f47503 Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Fri, 22 Feb 2019 02:11:38 -0500 Subject: [PATCH 26/40] Correct small isues with command naming --- Malmo/src/MissionSpec.cpp | 8 ++++ .../java/com/microsoft/Malmo/MalmoMod.java | 1 - Schemas/MissionHandlers.xsd | 6 +-- Schemas/MissionHandlers.xsd.in | 43 ++++++++----------- 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/Malmo/src/MissionSpec.cpp b/Malmo/src/MissionSpec.cpp index 8791244f5..9e867411e 100755 --- a/Malmo/src/MissionSpec.cpp +++ b/Malmo/src/MissionSpec.cpp @@ -39,6 +39,8 @@ namespace malmo const std::vector MissionSpec::all_inventory_commands = { "swapInventoryItems", "combineInventoryItems", "discardCurrentItem", "hotbar.1", "hotbar.2", "hotbar.3", "hotbar.4", "hotbar.5", "hotbar.6", "hotbar.7", "hotbar.8", "hotbar.9" }; const std::vector MissionSpec::all_simplecraft_commands = { "craft" }; + const std::vector MissionSpec::all_nearbycraft_commands = { "craftNearby" }; + const std::vector MissionSpec::all_nearbysmelt_commands = { "semlt" }; const std::vector MissionSpec::all_chat_commands = { "chat" }; const std::vector MissionSpec::all_mission_quit_commands = { "quit" }; const std::vector MissionSpec::all_human_level_commands = { "forward", "left", "right", "jump", "sneak", "sprint", "inventory", "swapHands", "drop", "use", "attack", "moveMouse", @@ -605,6 +607,12 @@ namespace malmo else if (command_handler == "SimpleCraft") { allowed_commands = all_simplecraft_commands; } + else if (command_handler == "NearbyCraft") { + allowed_commands = all_simplecraft_commands; + } + else if (command_handler == "NearbySmelt") { + allowed_commands = all_simplecraft_commands; + } else if (command_handler == "Chat") { allowed_commands = all_chat_commands; } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java b/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java index 4c8b189d5..bbc030e43 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java @@ -32,7 +32,6 @@ import java.util.Map; import java.util.Map.Entry; -import main.java.com.microsoft.Malmo.MissionHandlers.SimpleCraftNearbyCommandsImplementation; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd index 666d596dd..1d5bcb0a0 100644 --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -1455,7 +1455,7 @@ - + A command for simple nearby crafting: @@ -1470,7 +1470,7 @@ - + A command for simple smelting: @@ -1568,7 +1568,7 @@ - + diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index 28b767452..4a91670d0 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -6,10 +6,10 @@ xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" elementFormDefault="qualified" jaxb:version="2.1" - version="${MALMO_VERSION_MAJOR}.${MALMO_VERSION_MINOR}"> + version="0.37"> - + @@ -1257,9 +1257,9 @@ "{{{strafe -1}}}" - start moving left at 100% of the normal walking speed (-ve = left, +ve = right). - "{{{pitch 0.1}}}" - start tilting the agent's head down at 10% of the maximum speed (-ve = up, +ve = down). The maximum speed is set by {{{turnSpeedDegs}}} in {{{ContinuousMovementCommands}}}. + "{{{pitch 0.1}}}" - start tilting the agent's head down at 10% of the maximum speed (-ve = up, +ve = down). The maximum speed is set by {{{turnSpeedDegs}}} in {{{ContinuousMovementCommands}}}. - "{{{turn 0.1}}}" - start turning right at 10% of the maximum speed (-ve = anti-clockwise/left, +ve = clockwise/right). The maximum speed is set by {{{turnSpeedDegs}}} in {{{ContinuousMovementCommands}}}. + "{{{turn 0.1}}}" - start turning right at 10% of the maximum speed (-ve = anti-clockwise/left, +ve = clockwise/right). The maximum speed is set by {{{turnSpeedDegs}}} in {{{ContinuousMovementCommands}}}. "{{{jump 1}}}" - start jumping (1 = start, 0 = stop). @@ -1267,7 +1267,7 @@ "{{{attack 1}}}" - start attacking (1 = start, 0 = stop). The 'attack' command is for destroying blocks and attacking mobs. - "{{{use 1}}}" - start 'use'ing (1 = start, 0 = stop). The 'use' command is for placing blocks and for other things too. + "{{{use 1}}}" - start 'use'ing (1 = start, 0 = stop). The 'use' command is for placing blocks and for other things too. @@ -1401,10 +1401,10 @@ To select a hotbar slot: - "{{{hotbar.1 1}}}" - "{{{hotbar.1 0}}}" + "{{{hotbar.1 1}}}" + "{{{hotbar.1 0}}}" - Send both commands to select hotbar slot 1 as the currently-held tool. This affects the attack and use commands + Send both commands to select hotbar slot 1 as the currently-held tool. This affects the attack and use commands - e.g. if the agent does 'use' while holding a block item it will place the block into the world. If the agent is currently pointed at a container item - eg a chest, shulker box, dispenser etc - then the swap and combine commands @@ -1415,7 +1415,7 @@ "{{{swapInventoryItems 3 Chest:0}}}" - Note that this is the same as writing + Note that this is the same as writing "{{{swapInventoryItems Inventory:3 Chest:0}}}" @@ -1445,14 +1445,6 @@ A command for simple crafting: - Will look up all recipes that produce the requested object, and attempt each one in turn until one is successful or all have failed. This ignores all issues like requiring a crafting table / brewing stand etc, and the shape of the recipe (which items go in which slots on the crafting table). It will simply check to see whether the player has the necessary raw ingredients, and, if so, will remove them from the player's inventory and add the result of the recipe. - - For basic objects, use the ItemTypes or BlockTypes found in Types.xsd. Eg: - - "{{{craft diamond_pickaxe}}}" will remove three diamonds and two sticks from the player's inventory, and add a diamond pickaxe. - - For more control over colours, types etc, add a Variation or Colour. Eg: - "{{{craft carpet PINK}}}" etc. @@ -1463,8 +1455,7 @@ - - + A command for simple nearby crafting: @@ -1479,12 +1470,12 @@ - + A command for simple smelting: - "{{{smelt carpet PINK}}}" + "{{{smeltNearby carpet PINK}}}" etc. @@ -1493,7 +1484,7 @@ - + @@ -1577,7 +1568,7 @@ - + @@ -1737,7 +1728,7 @@ - + @@ -1752,7 +1743,7 @@ - + @@ -1782,7 +1773,7 @@ - + From 36e611c58362699a6a50868b74d5deb977619e0f Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Fri, 22 Feb 2019 02:11:52 -0500 Subject: [PATCH 27/40] Fix API --- Malmo/src/MissionSpec.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Malmo/src/MissionSpec.cpp b/Malmo/src/MissionSpec.cpp index 9e867411e..4be5ababc 100755 --- a/Malmo/src/MissionSpec.cpp +++ b/Malmo/src/MissionSpec.cpp @@ -608,10 +608,10 @@ namespace malmo allowed_commands = all_simplecraft_commands; } else if (command_handler == "NearbyCraft") { - allowed_commands = all_simplecraft_commands; + allowed_commands = all_nearbycraft_commands; } else if (command_handler == "NearbySmelt") { - allowed_commands = all_simplecraft_commands; + allowed_commands = all_nearbysmelt_commands; } else if (command_handler == "Chat") { allowed_commands = all_chat_commands; From a4500e3a2a9eb0d111b4a8ec295002ab5321071e Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Fri, 22 Feb 2019 02:20:10 -0500 Subject: [PATCH 28/40] Fix api integration --- Malmo/src/MissionSpec.cpp | 2 +- Malmo/src/MissionSpec.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Malmo/src/MissionSpec.cpp b/Malmo/src/MissionSpec.cpp index 4be5ababc..3d7fd48c7 100755 --- a/Malmo/src/MissionSpec.cpp +++ b/Malmo/src/MissionSpec.cpp @@ -40,7 +40,7 @@ namespace malmo "hotbar.1", "hotbar.2", "hotbar.3", "hotbar.4", "hotbar.5", "hotbar.6", "hotbar.7", "hotbar.8", "hotbar.9" }; const std::vector MissionSpec::all_simplecraft_commands = { "craft" }; const std::vector MissionSpec::all_nearbycraft_commands = { "craftNearby" }; - const std::vector MissionSpec::all_nearbysmelt_commands = { "semlt" }; + const std::vector MissionSpec::all_nearbysmelt_commands = { "smeltNearby" }; const std::vector MissionSpec::all_chat_commands = { "chat" }; const std::vector MissionSpec::all_mission_quit_commands = { "quit" }; const std::vector MissionSpec::all_human_level_commands = { "forward", "left", "right", "jump", "sneak", "sprint", "inventory", "swapHands", "drop", "use", "attack", "moveMouse", diff --git a/Malmo/src/MissionSpec.h b/Malmo/src/MissionSpec.h index c5f644927..2595495b4 100755 --- a/Malmo/src/MissionSpec.h +++ b/Malmo/src/MissionSpec.h @@ -386,6 +386,8 @@ namespace malmo static const std::vector all_discrete_movement_commands; static const std::vector all_inventory_commands; static const std::vector all_simplecraft_commands; + static const std::vector all_nearbycraft_commands; + static const std::vector all_nearbysmelt_commands; static const std::vector all_chat_commands; static const std::vector all_mission_quit_commands; static const std::vector all_human_level_commands; From 96ab4d64c77bac5dfc3617e53c40c3202d95b6aa Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Fri, 22 Feb 2019 02:27:02 -0500 Subject: [PATCH 29/40] Update value of craft and smelt nearby command --- .../MissionHandlers/NearbyCraftCommandsImplementation.java | 2 +- .../MissionHandlers/NearbySmeltCommandsImplementation.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java index 00569f912..f955691cb 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java @@ -143,7 +143,7 @@ public IMessage onMessage(CraftMessage message, MessageContext ctx) { @Override protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { - if (verb.equalsIgnoreCase(NearbyCraftCommand.CRAFT.value())) { + if (verb.equalsIgnoreCase(NearbyCraftCommand.CRAFTNEARBY.value())) { MalmoMod.network.sendToServer(new CraftMessage(parameter)); return true; } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java index 263617e53..b8b6db6b5 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java @@ -141,7 +141,7 @@ public IMessage onMessage(CraftMessage message, MessageContext ctx) { @Override protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { - if (verb.equalsIgnoreCase(NearbySmeltCommand.CRAFT.value())) { + if (verb.equalsIgnoreCase(NearbySmeltCommand.SMELTNEARBY.value())) { MalmoMod.network.sendToServer(new CraftMessage(parameter)); return true; } From bbdc0d42ca16e1bb7bec80b7319e2a6f1ab6fb2d Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Fri, 22 Feb 2019 02:44:35 -0500 Subject: [PATCH 30/40] Add new commands to python api =( --- MalmoEnv/malmoenv/commands.py | 20 ++++++++++++++++++++ Schemas/MissionHandlers.xsd.in | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/MalmoEnv/malmoenv/commands.py b/MalmoEnv/malmoenv/commands.py index b428a9aa6..27b6bdd7f 100644 --- a/MalmoEnv/malmoenv/commands.py +++ b/MalmoEnv/malmoenv/commands.py @@ -35,6 +35,8 @@ class CommandParser: inventoryCommands = "Inventory" chatCommands = "Chat" simpleCraftCommands = "SimpleCraft" + nearbyCraftCommands = "NearbyCraft" + nearbySmeltCommands = "NearbySmelt" missionQuitCommands = "MissionQuit" humanLevelCommands = "HumanLevel" @@ -50,6 +52,8 @@ class CommandParser: "hotbar.7", "hotbar.8", "hotbar.9"] all_chat = ["chat"] all_simplecraft = ["craft"] + all_nearbycraft = ["nearbyCraft"] + all_nearbysmelt = ["nearbySmelt"] all_mission_quit = ["quit"] all_human_level = ["forward", "left", "right", "jump", "sneak", "sprint", "inventory", "swapHands", "drop", "use", "attack", "moveMouse", @@ -126,6 +130,14 @@ def get_actions(self, commands): if verb != 'chat': raise CommandHandlerException("Invalid chat command") actions.append(verb) + elif type == 'NearbyCraft': + if verb != 'nearbyCraft': + raise CommandHandlerException("Invalid nearby craft command") + actions.append(verb) + elif type == 'NearbySmelt': + if verb != 'nearbySmelt': + raise CommandHandlerException("Invalid nearby smelt command") + actions.append(verb) elif type == 'SimpleCraft': if verb != 'craft': raise CommandHandlerException("Invalid craft command") @@ -152,6 +164,10 @@ def _command_hander(self, handlers, turnbased, commands): commands.extend(self._add_commands(CommandParser.chatCommands, turnbased, ch)) elif ch.tag == CommandParser.ns + "SimpleCraftCommands": commands.extend(self._add_commands(CommandParser.simpleCraftCommands, turnbased, ch)) + elif ch.tag == CommandParser.ns + "NearbyCraftCommands": + commands.extend(self._add_commands(CommandParser.nearbyCraftCommands, turnbased, ch)) + elif ch.tag == CommandParser.ns + "NearbySmeltCommands": + commands.extend(self._add_commands(CommandParser.nearbySmeltCommands, turnbased, ch)) elif ch.tag == CommandParser.ns + "MissionQuitCommands": commands.extend(self._add_commands(CommandParser.missionQuitCommands, turnbased, ch)) elif ch.tag == CommandParser.ns + "HumanLevelCommands": @@ -189,6 +205,10 @@ def _fill_command_list(self, command_type, turnbased, allow, deny): allow = [(command_type, turnbased, c) for c in CommandParser.all_human_level] elif command_type == CommandParser.simpleCraftCommands: allow = [(command_type, turnbased, c) for c in CommandParser.all_simplecraft] + elif command_type == CommandParser.nearbyCraftCommands: + allow = [(command_type, turnbased, c) for c in CommandParser.all_nearbycraft] + elif command_type == CommandParser.nearbySmeltCommands: + allow = [(command_type, turnbased, c) for c in CommandParser.all_nearbysmelt] elif command_type == CommandParser.missionQuitCommands: allow = [(command_type, turnbased, c) for c in CommandParser.missionQuitCommands] elif command_type == CommandParser.chatCommands: diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index 4a91670d0..bd35f612e 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -1466,7 +1466,7 @@ - + @@ -1481,7 +1481,7 @@ - + From 8c2cb181977993bd38c757f4d7b60f000baf7a0c Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Fri, 22 Feb 2019 02:53:53 -0500 Subject: [PATCH 31/40] Revert testing change --- Schemas/MissionHandlers.xsd.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Schemas/MissionHandlers.xsd.in b/Schemas/MissionHandlers.xsd.in index bd35f612e..4a91670d0 100644 --- a/Schemas/MissionHandlers.xsd.in +++ b/Schemas/MissionHandlers.xsd.in @@ -1466,7 +1466,7 @@ - + @@ -1481,7 +1481,7 @@ - + From b2c5f9385d67b71589e23d6f9b80d2ca665e9ae4 Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Fri, 22 Feb 2019 03:00:16 -0500 Subject: [PATCH 32/40] Skrew the API --- .../MissionHandlers/NearbyCraftCommandsImplementation.java | 2 +- .../MissionHandlers/NearbySmeltCommandsImplementation.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java index f955691cb..c205fbbb7 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java @@ -143,7 +143,7 @@ public IMessage onMessage(CraftMessage message, MessageContext ctx) { @Override protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { - if (verb.equalsIgnoreCase(NearbyCraftCommand.CRAFTNEARBY.value())) { + if (verb.equalsIgnoreCase('craftNearby')) { MalmoMod.network.sendToServer(new CraftMessage(parameter)); return true; } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java index b8b6db6b5..0c4fe3f47 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java @@ -141,7 +141,7 @@ public IMessage onMessage(CraftMessage message, MessageContext ctx) { @Override protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { - if (verb.equalsIgnoreCase(NearbySmeltCommand.SMELTNEARBY.value())) { + if (verb.equalsIgnoreCase('smeltNearby')) { MalmoMod.network.sendToServer(new CraftMessage(parameter)); return true; } From 89680e79dc6af53ee00f9ecd551963e8b76f6544 Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Fri, 22 Feb 2019 03:20:36 -0500 Subject: [PATCH 33/40] Java != Python --- .../MissionHandlers/NearbyCraftCommandsImplementation.java | 2 +- .../MissionHandlers/NearbySmeltCommandsImplementation.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java index c205fbbb7..b66fed739 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java @@ -143,7 +143,7 @@ public IMessage onMessage(CraftMessage message, MessageContext ctx) { @Override protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { - if (verb.equalsIgnoreCase('craftNearby')) { + if (verb.equalsIgnoreCase("craftNearby")) { MalmoMod.network.sendToServer(new CraftMessage(parameter)); return true; } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java index 0c4fe3f47..da76fffa0 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java @@ -141,7 +141,7 @@ public IMessage onMessage(CraftMessage message, MessageContext ctx) { @Override protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { - if (verb.equalsIgnoreCase('smeltNearby')) { + if (verb.equalsIgnoreCase("smeltNearby")) { MalmoMod.network.sendToServer(new CraftMessage(parameter)); return true; } From 3df3ebb448793ac00358d565480e50c699a01d09 Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Fri, 22 Feb 2019 17:06:18 -0500 Subject: [PATCH 34/40] Made things strictly better --- .../src/main/java/com/microsoft/Malmo/MalmoMod.java | 12 ++---------- .../MissionHandlers/PlaceCommandsImplementation.java | 5 ++++- Schemas/Mission.xsd.in | 1 + 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java b/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java index bbc030e43..57a72dbd2 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java @@ -19,6 +19,7 @@ package com.microsoft.Malmo; +import com.microsoft.Malmo.MissionHandlers.*; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufInputStream; import io.netty.buffer.ByteBufOutputStream; @@ -57,16 +58,6 @@ import net.minecraftforge.fml.relauncher.Side; import com.microsoft.Malmo.Client.MalmoModClient; -import com.microsoft.Malmo.MissionHandlers.AbsoluteMovementCommandsImplementation; -import com.microsoft.Malmo.MissionHandlers.DiscreteMovementCommandsImplementation; -import com.microsoft.Malmo.MissionHandlers.InventoryCommandsImplementation; -import com.microsoft.Malmo.MissionHandlers.ObservationFromFullInventoryImplementation; -import com.microsoft.Malmo.MissionHandlers.ObservationFromFullStatsImplementation; -import com.microsoft.Malmo.MissionHandlers.ObservationFromGridImplementation; -import com.microsoft.Malmo.MissionHandlers.ObservationFromSystemImplementation; -import com.microsoft.Malmo.MissionHandlers.SimpleCraftCommandsImplementation; -import com.microsoft.Malmo.MissionHandlers.NearbyCraftCommandsImplementation; -import com.microsoft.Malmo.MissionHandlers.NearbySmeltCommandsImplementation; import com.microsoft.Malmo.Schemas.MissionInit; import com.microsoft.Malmo.Server.MalmoModServer; import com.microsoft.Malmo.Utils.AddressHelper; @@ -138,6 +129,7 @@ public void preInit(FMLPreInitializationEvent event) network.registerMessage(SimpleCraftCommandsImplementation.CraftMessageHandler.class, SimpleCraftCommandsImplementation.CraftMessage.class, 4, Side.SERVER); network.registerMessage(NearbyCraftCommandsImplementation.CraftMessageHandler.class, NearbyCraftCommandsImplementation.CraftMessage.class, 4, Side.SERVER); network.registerMessage(NearbySmeltCommandsImplementation.CraftMessageHandler.class, NearbySmeltCommandsImplementation.CraftMessage.class, 4, Side.SERVER); + network.registerMessage(PlaceCommandsImplementation.PlaceMessage.class, PlaceCommandsImplementation.PlaceMessage.class, 4, Side.SERVER); network.registerMessage(AbsoluteMovementCommandsImplementation.TeleportMessageHandler.class, AbsoluteMovementCommandsImplementation.TeleportMessage.class, 5, Side.SERVER); network.registerMessage(MalmoMessageHandler.class, MalmoMessage.class, 6, Side.SERVER); // Malmo messages from client to server network.registerMessage(InventoryCommandsImplementation.InventoryMessageHandler.class, InventoryCommandsImplementation.InventoryMessage.class, 7, Side.SERVER); diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java index 3cb3bfe6a..578a4b737 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java @@ -20,6 +20,9 @@ package com.microsoft.Malmo.MissionHandlers; import com.microsoft.Malmo.Schemas.*; +import com.microsoft.Malmo.Schemas.MissionInit; +import com.microsoft.Malmo.Schemas.NearbySmeltCommand; +import com.microsoft.Malmo.Schemas.NearbySmeltCommands; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; @@ -51,7 +54,7 @@ protected boolean onExecute(String verb, String parameter, MissionInit missionIn if (player == null) return false; - if (!verb.equalsIgnoreCase(PlaceCommand.PLACE.value())) + if (!verb.equalsIgnoreCase("place")) return false; InventoryPlayer inv = player.inventory; diff --git a/Schemas/Mission.xsd.in b/Schemas/Mission.xsd.in index 63ea05613..3c37fb865 100644 --- a/Schemas/Mission.xsd.in +++ b/Schemas/Mission.xsd.in @@ -373,6 +373,7 @@ + From 7a901e9453b3a8c082bfd14a456c23f4afc3da68 Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Fri, 22 Feb 2019 17:11:19 -0500 Subject: [PATCH 35/40] Dont do silly things --- Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java b/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java index 57a72dbd2..a2c7c7d8b 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java @@ -129,7 +129,6 @@ public void preInit(FMLPreInitializationEvent event) network.registerMessage(SimpleCraftCommandsImplementation.CraftMessageHandler.class, SimpleCraftCommandsImplementation.CraftMessage.class, 4, Side.SERVER); network.registerMessage(NearbyCraftCommandsImplementation.CraftMessageHandler.class, NearbyCraftCommandsImplementation.CraftMessage.class, 4, Side.SERVER); network.registerMessage(NearbySmeltCommandsImplementation.CraftMessageHandler.class, NearbySmeltCommandsImplementation.CraftMessage.class, 4, Side.SERVER); - network.registerMessage(PlaceCommandsImplementation.PlaceMessage.class, PlaceCommandsImplementation.PlaceMessage.class, 4, Side.SERVER); network.registerMessage(AbsoluteMovementCommandsImplementation.TeleportMessageHandler.class, AbsoluteMovementCommandsImplementation.TeleportMessage.class, 5, Side.SERVER); network.registerMessage(MalmoMessageHandler.class, MalmoMessage.class, 6, Side.SERVER); // Malmo messages from client to server network.registerMessage(InventoryCommandsImplementation.InventoryMessageHandler.class, InventoryCommandsImplementation.InventoryMessage.class, 7, Side.SERVER); From d284fdbfa2629ef4c1155fbc57ed6d9eef8e1a1d Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Fri, 22 Feb 2019 19:03:52 -0500 Subject: [PATCH 36/40] Make new messeges to pass to cute squirrels --- .../src/main/java/com/microsoft/Malmo/MalmoMod.java | 4 ++-- .../NearbyCraftCommandsImplementation.java | 12 ++++++------ .../NearbySmeltCommandsImplementation.java | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java b/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java index a2c7c7d8b..b0d9362d7 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java @@ -127,8 +127,8 @@ public void preInit(FMLPreInitializationEvent event) network.registerMessage(ObservationFromGridImplementation.GridRequestMessageHandler.class, ObservationFromGridImplementation.GridRequestMessage.class, 2, Side.SERVER); network.registerMessage(MalmoMessageHandler.class, MalmoMessage.class, 3, Side.CLIENT); // Malmo messages from server to client network.registerMessage(SimpleCraftCommandsImplementation.CraftMessageHandler.class, SimpleCraftCommandsImplementation.CraftMessage.class, 4, Side.SERVER); - network.registerMessage(NearbyCraftCommandsImplementation.CraftMessageHandler.class, NearbyCraftCommandsImplementation.CraftMessage.class, 4, Side.SERVER); - network.registerMessage(NearbySmeltCommandsImplementation.CraftMessageHandler.class, NearbySmeltCommandsImplementation.CraftMessage.class, 4, Side.SERVER); + network.registerMessage(NearbyCraftCommandsImplementation.CraftNearbyMessageHandler.class, NearbyCraftCommandsImplementation.CraftNearbyMessage.class, 4, Side.SERVER); + network.registerMessage(NearbySmeltCommandsImplementation.SmeltNearbyMessageHandler.class, NearbySmeltCommandsImplementation.SmeltNearbyMessage.class, 4, Side.SERVER); network.registerMessage(AbsoluteMovementCommandsImplementation.TeleportMessageHandler.class, AbsoluteMovementCommandsImplementation.TeleportMessage.class, 5, Side.SERVER); network.registerMessage(MalmoMessageHandler.class, MalmoMessage.class, 6, Side.SERVER); // Malmo messages from client to server network.registerMessage(InventoryCommandsImplementation.InventoryMessageHandler.class, InventoryCommandsImplementation.InventoryMessage.class, 7, Side.SERVER); diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java index b66fed739..30279c657 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java @@ -52,13 +52,13 @@ public class NearbyCraftCommandsImplementation extends CommandBase { private boolean isOverriding; private static ArrayList craftingTables; - public static class CraftMessage implements IMessage { + public static class CraftNearbyMessage implements IMessage { String parameters; - public CraftMessage() { + public CraftNearbyMessage() { } - public CraftMessage(String parameters) { + public CraftNearbyMessage(String parameters) { this.parameters = parameters; } @@ -87,9 +87,9 @@ public void onBlockDestroy(BlockEvent.BreakEvent event) { craftingTables.remove(i); } - public static class CraftMessageHandler implements IMessageHandler { + public static class CraftNearbyMessageHandler implements IMessageHandler { @Override - public IMessage onMessage(CraftMessage message, MessageContext ctx) { + public IMessage onMessage(CraftNearbyMessage message, MessageContext ctx) { EntityPlayerMP player = ctx.getServerHandler().playerEntity; Vec3d headPos = new Vec3d(player.posX, player.posY + 1.6, player.posZ); @@ -144,7 +144,7 @@ public IMessage onMessage(CraftMessage message, MessageContext ctx) { @Override protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { if (verb.equalsIgnoreCase("craftNearby")) { - MalmoMod.network.sendToServer(new CraftMessage(parameter)); + MalmoMod.network.sendToServer(new CraftNearbyMessage(parameter)); return true; } return false; diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java index da76fffa0..832226aa7 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java @@ -51,13 +51,13 @@ public class NearbySmeltCommandsImplementation extends CommandBase { private boolean isOverriding; private static ArrayList furnaces; - public static class CraftMessage implements IMessage { + public static class SmeltNearbyMessage implements IMessage { String parameters; - public CraftMessage() { + public SmeltNearbyMessage() { } - public CraftMessage(String parameters) { + public SmeltNearbyMessage(String parameters) { this.parameters = parameters; } @@ -86,9 +86,9 @@ public void onBlockDestroy(BlockEvent.BreakEvent event) { furnaces.remove(i); } - public static class CraftMessageHandler implements IMessageHandler { + public static class SmeltNearbyMessageHandler implements IMessageHandler { @Override - public IMessage onMessage(CraftMessage message, MessageContext ctx) { + public IMessage onMessage(SmeltNearbyMessage message, MessageContext ctx) { EntityPlayerMP player = ctx.getServerHandler().playerEntity; Vec3d headPos = new Vec3d(player.posX, player.posY + 1.6, player.posZ); @@ -142,7 +142,7 @@ public IMessage onMessage(CraftMessage message, MessageContext ctx) { @Override protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { if (verb.equalsIgnoreCase("smeltNearby")) { - MalmoMod.network.sendToServer(new CraftMessage(parameter)); + MalmoMod.network.sendToServer(new SmeltNearbyMessage(parameter)); return true; } return false; From 04a3c26bffc116d82086b86ceda285517e499c7a Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Sat, 23 Feb 2019 12:30:08 -0500 Subject: [PATCH 37/40] Likely need a new channel for each message Attempt to fix placeblock not decreasing bug --- Malmo/src/MissionSpec.cpp | 6 +++--- Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java | 4 ++-- .../Malmo/MissionHandlers/PlaceCommandsImplementation.java | 4 ++-- Schemas/Mission.xsd.in | 2 ++ 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Malmo/src/MissionSpec.cpp b/Malmo/src/MissionSpec.cpp index 3d7fd48c7..3b01d884c 100755 --- a/Malmo/src/MissionSpec.cpp +++ b/Malmo/src/MissionSpec.cpp @@ -384,8 +384,8 @@ namespace malmo child.erase("DiscreteMovementCommands"); child.erase("AbsoluteMovementCommands"); child.erase("SimpleCraftCommands"); - child.erase("SimpleCraftCraftCommands"); - child.erase("SimpleSmeltCommands"); + child.erase("NearbyCraftCommands"); + child.erase("NearbySmeltCommands"); child.erase("PlaceCommands"); child.erase("ChatCommands"); child.erase("MissionQuitCommands"); @@ -431,7 +431,7 @@ namespace malmo { addVerbToCommandType(verb, "Mission.AgentSection.AgentHandlers.InventoryCommands"); } - + void MissionSpec::allowAllChatCommands() { mission.put("Mission.AgentSection.AgentHandlers.ChatCommands", ""); diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java b/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java index b0d9362d7..1f1c7ddca 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MalmoMod.java @@ -127,8 +127,8 @@ public void preInit(FMLPreInitializationEvent event) network.registerMessage(ObservationFromGridImplementation.GridRequestMessageHandler.class, ObservationFromGridImplementation.GridRequestMessage.class, 2, Side.SERVER); network.registerMessage(MalmoMessageHandler.class, MalmoMessage.class, 3, Side.CLIENT); // Malmo messages from server to client network.registerMessage(SimpleCraftCommandsImplementation.CraftMessageHandler.class, SimpleCraftCommandsImplementation.CraftMessage.class, 4, Side.SERVER); - network.registerMessage(NearbyCraftCommandsImplementation.CraftNearbyMessageHandler.class, NearbyCraftCommandsImplementation.CraftNearbyMessage.class, 4, Side.SERVER); - network.registerMessage(NearbySmeltCommandsImplementation.SmeltNearbyMessageHandler.class, NearbySmeltCommandsImplementation.SmeltNearbyMessage.class, 4, Side.SERVER); + network.registerMessage(NearbyCraftCommandsImplementation.CraftNearbyMessageHandler.class, NearbyCraftCommandsImplementation.CraftNearbyMessage.class, 13, Side.SERVER); + network.registerMessage(NearbySmeltCommandsImplementation.SmeltNearbyMessageHandler.class, NearbySmeltCommandsImplementation.SmeltNearbyMessage.class, 14, Side.SERVER); network.registerMessage(AbsoluteMovementCommandsImplementation.TeleportMessageHandler.class, AbsoluteMovementCommandsImplementation.TeleportMessage.class, 5, Side.SERVER); network.registerMessage(MalmoMessageHandler.class, MalmoMessage.class, 6, Side.SERVER); // Malmo messages from client to server network.registerMessage(InventoryCommandsImplementation.InventoryMessageHandler.class, InventoryCommandsImplementation.InventoryMessage.class, 7, Side.SERVER); diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java index 578a4b737..59d6e6443 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java @@ -67,7 +67,7 @@ protected boolean onExecute(String verb, String parameter, MissionInit missionIn ItemStack s = inv.getStackInSlot(i).copy(); if (b.getRegistryName().equals(s.getItem().getRegistryName())) { int selectedHotBarItem = inv.currentItem; - ItemStack selected = inv.getStackInSlot(selectedHotBarItem).copy(); +// ItemStack selected = inv.getStackInSlot(selectedHotBarItem).copy(); inv.setInventorySlotContents(selectedHotBarItem, s); RayTraceResult mop = Minecraft.getMinecraft().objectMouseOver; @@ -100,7 +100,7 @@ protected boolean onExecute(String verb, String parameter, MissionInit missionIn foundBlock = true; inv.setInventorySlotContents(i, inv.getCurrentItem()); - inv.setInventorySlotContents(selectedHotBarItem, selected); +// inv.setInventorySlotContents(selectedHotBarItem, selected); } } diff --git a/Schemas/Mission.xsd.in b/Schemas/Mission.xsd.in index 3c37fb865..056b460ca 100644 --- a/Schemas/Mission.xsd.in +++ b/Schemas/Mission.xsd.in @@ -407,6 +407,8 @@ + + From b188b83ac08b439e9993611cfc7f73d8ed3105dd Mon Sep 17 00:00:00 2001 From: Brandon Houghton Date: Sat, 23 Feb 2019 16:21:05 -0500 Subject: [PATCH 38/40] Check for non-existant items --- .../src/main/java/com/microsoft/Malmo/Utils/CraftingHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/Utils/CraftingHelper.java b/Minecraft/src/main/java/com/microsoft/Malmo/Utils/CraftingHelper.java index c8129fdaa..1e6964b70 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/Utils/CraftingHelper.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/Utils/CraftingHelper.java @@ -338,7 +338,7 @@ public static List getRecipesForRequestedOutput(String output) if (obj instanceof IRecipe) { ItemStack is = ((IRecipe)obj).getRecipeOutput(); - if (is == null) + if (is == null || target == null) continue; if (ItemStack.areItemsEqual(is, target)) { From 5a8de6bc8ef7b42b42c2bd2fcfc2b8f8ae666bb4 Mon Sep 17 00:00:00 2001 From: ccodel Date: Thu, 28 Feb 2019 17:33:00 -0500 Subject: [PATCH 39/40] Updated place logic --- .../PlaceCommandsImplementation.java | 49 ++++++++++++++++--- .../SimpleCraftCommandsImplementation.java | 2 +- .../microsoft/Malmo/Utils/CraftingHelper.java | 27 ++++++++++ Minecraft/src/main/resources/schemas.index | 4 +- Schemas/Mission.xsd | 3 ++ Schemas/MissionHandlers.xsd | 30 ++++++------ 6 files changed, 89 insertions(+), 26 deletions(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java index 59d6e6443..aa23a8ce4 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/PlaceCommandsImplementation.java @@ -19,26 +19,20 @@ package com.microsoft.Malmo.MissionHandlers; +import com.microsoft.Malmo.MalmoMod; import com.microsoft.Malmo.Schemas.*; import com.microsoft.Malmo.Schemas.MissionInit; -import com.microsoft.Malmo.Schemas.NearbySmeltCommand; -import com.microsoft.Malmo.Schemas.NearbySmeltCommands; import net.minecraft.block.Block; -import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import com.microsoft.Malmo.MissionHandlerInterfaces.ICommandHandler; import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumHand; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; -import net.minecraftforge.common.util.BlockSnapshot; -import net.minecraftforge.event.entity.player.PlayerInteractEvent; -import net.minecraftforge.event.world.BlockEvent; -import net.minecraftforge.common.MinecraftForge; /** * @author Cayden Codel, Carnegie Mellon University @@ -57,6 +51,44 @@ protected boolean onExecute(String verb, String parameter, MissionInit missionIn if (!verb.equalsIgnoreCase("place")) return false; + Item item = Item.getByNameOrId(parameter); + Block block = Block.getBlockFromItem(item); + if (item == null || item.getRegistryName() == null || block.getRegistryName() == null) + return false; + + InventoryPlayer inv = player.inventory; + boolean blockInInventory = false; + ItemStack stackInInventory = null; + int stackIndex = -1; + for (int i = 0; !blockInInventory && i < inv.getSizeInventory(); i++) { + Item stack = inv.getStackInSlot(i).getItem(); + if (stack.getRegistryName() != null && stack.getRegistryName().equals(item.getRegistryName())) { + stackInInventory = inv.getStackInSlot(i); + stackIndex = i; + blockInInventory = true; + } + } + + // We don't have that item in our inventories + if (!blockInInventory) + return false; + + RayTraceResult mop = Minecraft.getMinecraft().objectMouseOver; + if (mop.typeOfHit == RayTraceResult.Type.BLOCK) { + BlockPos pos = mop.getBlockPos().add(mop.sideHit.getDirectionVec()); + // Can we place this block here? + AxisAlignedBB axisalignedbb = block.getDefaultState().getCollisionBoundingBox(player.world, pos); + if (axisalignedbb == null || player.world.checkNoEntityCollision(axisalignedbb.offset(pos), null)) { + MalmoMod.network.sendToServer(new DiscreteMovementCommandsImplementation.UseActionMessage(mop.getBlockPos(), new ItemStack(block), mop.sideHit, false, mop.hitVec)); + if (stackInInventory.getCount() == 1) + inv.setInventorySlotContents(stackIndex, new ItemStack(Block.getBlockById(0))); + else + stackInInventory.setCount(stackInInventory.getCount() - 1); + } + } + + /* + InventoryPlayer inv = player.inventory; Block b = Block.getBlockFromName(parameter); if (b == null || b.getRegistryName() == null) @@ -103,6 +135,7 @@ protected boolean onExecute(String verb, String parameter, MissionInit missionIn // inv.setInventorySlotContents(selectedHotBarItem, selected); } } + */ return true; } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/SimpleCraftCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/SimpleCraftCommandsImplementation.java index d550377a4..9efd6fa46 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/SimpleCraftCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/SimpleCraftCommandsImplementation.java @@ -104,7 +104,7 @@ protected boolean onExecute(String verb, String parameter, MissionInit missionIn @Override public boolean parseParameters(Object params) { - if (params == null || !(params instanceof SimpleCraftCommands)) + if (!(params instanceof SimpleCraftCommands)) return false; SimpleCraftCommands cparams = (SimpleCraftCommands)params; diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/Utils/CraftingHelper.java b/Minecraft/src/main/java/com/microsoft/Malmo/Utils/CraftingHelper.java index 1e6964b70..3f22ecf5a 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/Utils/CraftingHelper.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/Utils/CraftingHelper.java @@ -41,6 +41,7 @@ import net.minecraft.block.properties.PropertyDirection; import net.minecraft.block.properties.PropertyEnum; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Blocks; @@ -202,6 +203,32 @@ public static boolean playerHasIngredients(EntityPlayerMP player, List + * The ingredients list MUST be amalgamated such that no two ItemStacks contain the same type of item. + * @param player + * @param ingredients an amalgamated list of ingredients + * @return true if the player's inventory contains sufficient quantities of all the required items. + */ + public static boolean playerHasIngredients(EntityPlayerSP player, List ingredients) + { + NonNullList main = player.inventory.mainInventory; + NonNullList arm = player.inventory.armorInventory; + + for (ItemStack isIngredient : ingredients) + { + int target = isIngredient.getCount(); + for (int i = 0; i < main.size() + arm.size() && target > 0; i++) + { + ItemStack isPlayer = (i >= main.size()) ? arm.get(i - main.size()) : main.get(i); + if (isPlayer != null && isIngredient != null && itemStackIngredientsMatch(isPlayer, isIngredient)) + target -= isPlayer.getCount(); + } + if (target > 0) + return false; // Don't have enough of this. + } + return true; + } + /** Compare two ItemStacks and see if their items match - take wildcards into account, don't take stacksize into account. * @param A ItemStack A * @param B ItemStack B diff --git a/Minecraft/src/main/resources/schemas.index b/Minecraft/src/main/resources/schemas.index index 70b4a99d8..55dcedb71 100644 --- a/Minecraft/src/main/resources/schemas.index +++ b/Minecraft/src/main/resources/schemas.index @@ -1,5 +1,5 @@ -Mission.xsd -MissionEnded.xsd MissionHandlers.xsd MissionInit.xsd +MissionEnded.xsd Types.xsd +Mission.xsd diff --git a/Schemas/Mission.xsd b/Schemas/Mission.xsd index d4a5346db..0dd229ae3 100644 --- a/Schemas/Mission.xsd +++ b/Schemas/Mission.xsd @@ -373,6 +373,7 @@ + @@ -406,6 +407,8 @@ + + diff --git a/Schemas/MissionHandlers.xsd b/Schemas/MissionHandlers.xsd index 1d5bcb0a0..4a91670d0 100644 --- a/Schemas/MissionHandlers.xsd +++ b/Schemas/MissionHandlers.xsd @@ -9,7 +9,7 @@ version="0.37"> - + @@ -1257,9 +1257,9 @@ "{{{strafe -1}}}" - start moving left at 100% of the normal walking speed (-ve = left, +ve = right). - "{{{pitch 0.1}}}" - start tilting the agent's head down at 10% of the maximum speed (-ve = up, +ve = down). The maximum speed is set by {{{turnSpeedDegs}}} in {{{ContinuousMovementCommands}}}. + "{{{pitch 0.1}}}" - start tilting the agent's head down at 10% of the maximum speed (-ve = up, +ve = down). The maximum speed is set by {{{turnSpeedDegs}}} in {{{ContinuousMovementCommands}}}. - "{{{turn 0.1}}}" - start turning right at 10% of the maximum speed (-ve = anti-clockwise/left, +ve = clockwise/right). The maximum speed is set by {{{turnSpeedDegs}}} in {{{ContinuousMovementCommands}}}. + "{{{turn 0.1}}}" - start turning right at 10% of the maximum speed (-ve = anti-clockwise/left, +ve = clockwise/right). The maximum speed is set by {{{turnSpeedDegs}}} in {{{ContinuousMovementCommands}}}. "{{{jump 1}}}" - start jumping (1 = start, 0 = stop). @@ -1267,7 +1267,7 @@ "{{{attack 1}}}" - start attacking (1 = start, 0 = stop). The 'attack' command is for destroying blocks and attacking mobs. - "{{{use 1}}}" - start 'use'ing (1 = start, 0 = stop). The 'use' command is for placing blocks and for other things too. + "{{{use 1}}}" - start 'use'ing (1 = start, 0 = stop). The 'use' command is for placing blocks and for other things too. @@ -1401,10 +1401,10 @@ To select a hotbar slot: - "{{{hotbar.1 1}}}" - "{{{hotbar.1 0}}}" + "{{{hotbar.1 1}}}" + "{{{hotbar.1 0}}}" - Send both commands to select hotbar slot 1 as the currently-held tool. This affects the attack and use commands + Send both commands to select hotbar slot 1 as the currently-held tool. This affects the attack and use commands - e.g. if the agent does 'use' while holding a block item it will place the block into the world. If the agent is currently pointed at a container item - eg a chest, shulker box, dispenser etc - then the swap and combine commands @@ -1415,7 +1415,7 @@ "{{{swapInventoryItems 3 Chest:0}}}" - Note that this is the same as writing + Note that this is the same as writing "{{{swapInventoryItems Inventory:3 Chest:0}}}" @@ -1484,7 +1484,7 @@ - + @@ -1728,7 +1728,7 @@ - + @@ -1752,16 +1752,16 @@ - + When present, the Mod will accept simple commands that implement a basic form of smelting. Success of the smelt command depends on the presence of a nearby furnace previously placed by the agent and within reach and in field of view. Fails when a command corresponds to an item not able to be smelted. Each command takes fuel as if the agent had placed the items in a furnace. - + Eg: - + If called on 16 iron ore, requires 2 coal, 2 charcoal, 11 planks, etc. - + If called twice separately on 8 iron ore, requires 1 coal and then 1 coal, etc. @@ -1782,7 +1782,7 @@ - + From d2bf8991f4af96c4ba369ac1dfaa7f277a7d4e0a Mon Sep 17 00:00:00 2001 From: ccodel Date: Thu, 28 Feb 2019 20:24:44 -0500 Subject: [PATCH 40/40] Some little changes regarding Forge events, testing, making new branch to slash --- ...itFromTouchingBlockTypeImplementation.java | 1 - .../NearbyCraftCommandsImplementation.java | 24 ++++++++++++++++--- .../NearbySmeltCommandsImplementation.java | 2 +- .../SimpleCraftCommandsImplementation.java | 2 ++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromTouchingBlockTypeImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromTouchingBlockTypeImplementation.java index 73b2dab14..c42e15cc8 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromTouchingBlockTypeImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/AgentQuitFromTouchingBlockTypeImplementation.java @@ -32,7 +32,6 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import com.microsoft.Malmo.MissionHandlerInterfaces.IWantToQuit; -import com.microsoft.Malmo.MissionHandlers.RewardForCollectingItemImplementation.GainItemEvent; import com.microsoft.Malmo.Schemas.AgentQuitFromTouchingBlockType; import com.microsoft.Malmo.Schemas.BlockSpec; import com.microsoft.Malmo.Schemas.BlockSpecWithDescription; diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java index 30279c657..a7a08d951 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbyCraftCommandsImplementation.java @@ -26,10 +26,13 @@ import net.minecraft.block.BlockWorkbench; import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.crafting.IRecipe; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.living.LivingEvent; import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.network.ByteBufUtils; @@ -52,6 +55,14 @@ public class NearbyCraftCommandsImplementation extends CommandBase { private boolean isOverriding; private static ArrayList craftingTables; + @SubscribeEvent + public void onJump(LivingEvent.LivingJumpEvent event) { + if (event.getEntity() instanceof EntityPlayerSP) { + System.out.println("Jump! Attempting to craft sticks."); + onExecute("craftNearby", "stick", null); + } + } + public static class CraftNearbyMessage implements IMessage { String parameters; @@ -130,20 +141,25 @@ public IMessage onMessage(CraftNearbyMessage message, MessageContext ctx) { } if (closeTable) { + System.out.println("We are close enough to the table"); // We are close enough, try crafting recipes List matching_recipes = CraftingHelper.getRecipesForRequestedOutput(message.parameters); for (IRecipe recipe : matching_recipes) - if (CraftingHelper.attemptCrafting(player, recipe)) + if (CraftingHelper.attemptCrafting(player, recipe)) { + System.out.println("Crafted " + recipe.getRecipeOutput().toString()); return null; - } + } + } else + System.out.println("We are not close enough to a table"); + System.out.println("Either didn't have the requisite materials or weren't close enough to a table"); return null; } } @Override protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { - if (verb.equalsIgnoreCase("craftNearby")) { + if (verb.equalsIgnoreCase(NearbyCraftCommand.CRAFT_NEARBY.value())) { MalmoMod.network.sendToServer(new CraftNearbyMessage(parameter)); return true; } @@ -165,10 +181,12 @@ public boolean parseParameters(Object params) { @Override public void install(MissionInit missionInit) { CraftingHelper.reset(); + MinecraftForge.EVENT_BUS.register(this); } @Override public void deinstall(MissionInit missionInit) { + MinecraftForge.EVENT_BUS.unregister(this); } @Override diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java index 832226aa7..cff9f6a2a 100644 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/NearbySmeltCommandsImplementation.java @@ -141,7 +141,7 @@ public IMessage onMessage(SmeltNearbyMessage message, MessageContext ctx) { @Override protected boolean onExecute(String verb, String parameter, MissionInit missionInit) { - if (verb.equalsIgnoreCase("smeltNearby")) { + if (verb.equalsIgnoreCase(NearbySmeltCommand.SMELT_NEARBY.value())) { MalmoMod.network.sendToServer(new SmeltNearbyMessage(parameter)); return true; } diff --git a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/SimpleCraftCommandsImplementation.java b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/SimpleCraftCommandsImplementation.java index 9efd6fa46..90d943f5b 100755 --- a/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/SimpleCraftCommandsImplementation.java +++ b/Minecraft/src/main/java/com/microsoft/Malmo/MissionHandlers/SimpleCraftCommandsImplementation.java @@ -26,6 +26,8 @@ import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.IRecipe; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.common.network.ByteBufUtils; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;