I'm trying to make a small utility mod for Minecraft 1.7.10 in which you place a list of IDs in a config file and the mod removes their recipes from the game. I've got the config file working but I don't seem to be able to remove the recipes.
My method for removing the recipes is one I have seen in a couple of forum threads elsewhere and slightly modified to work with my config file (or not work in my case).
Here is the method:
private void removeRecipes(String toDelete)
{
ArrayList<?> recipes = (ArrayList<?>) CraftingManager.getInstance().getRecipeList();
ItemStack recipeResult = null;
ItemStack resultItem = new ItemStack((Item)Item.itemRegistry.getObject(toDelete));
resultItem.stackSize = 1;
resultItem.setItemDamage(0);
for (int scan = 0; scan < recipes.size(); scan++)
{
IRecipe tmpRecipe = (IRecipe) recipes.get(scan);
if (tmpRecipe instanceof ShapedRecipes)
{
ShapedRecipes recipe = (ShapedRecipes)tmpRecipe;
recipeResult = recipe.getRecipeOutput();
recipeResult.stackSize = 1;
recipeResult.setItemDamage(0);
}
if (tmpRecipe instanceof ShapelessRecipes)
{
ShapelessRecipes recipe = (ShapelessRecipes)tmpRecipe;
recipeResult = recipe.getRecipeOutput();
recipeResult.stackSize = 1;
recipeResult.setItemDamage(0);
}
if (ItemStack.areItemStacksEqual(resultItem, recipeResult))
{
System.out.println("[RecipeRemover] Removed Recipe: " + recipes.get(scan) + " -> " + recipeResult);
recipes.remove(scan);
}
}
}
Something was obviously a bit out with my code, but this is a much more efficient approach which works (and should work universally):
#SuppressWarnings("unchecked")
private void removeRecipes(String toDelete)
{
ItemStack resultItem = new ItemStack((Item)Item.itemRegistry.getObject(toDelete));
resultItem.stackSize = 1;
resultItem.setItemDamage(0);
List<IRecipe> recipes = CraftingManager.getInstance().getRecipeList();
for (int i = 0; i < recipes.size(); i++)
{
IRecipe tmpRecipe = recipes.get(i);
ItemStack recipeResult = tmpRecipe.getRecipeOutput();
if(recipeResult != null)
{
recipeResult.stackSize = 1;
recipeResult.setItemDamage(0);
}
if (ItemStack.areItemStacksEqual(resultItem, recipeResult))
{
recipes.remove(i--);
}
}
}
Related
I'm trying to use an array of objects to have barrels fall from the top of the screen to the bottom. (Like that old donkey kong game.) However, I can't seem to find a way to create more instances of the object than whatever the initial length of the array was. Anyone know a way to do this?
Here's the code:
Man Man;
Man background;
Man ladders;
PFont font1;
int time;
boolean run;
boolean newBarrel;
int barrelTotal;
Barrel[] barrel = new Barrel[100];
void setup() {
newBarrel = false;
run = true;
barrelTotal = 1;
time = millis();
size(800, 800);
Man = new Man();
background = new Man();
ladders = new Man();
for (int i = 0; i < barrel.length; i++) {
barrel[i] = new Barrel();
}
}
void draw() {
if (run == true) {
for (int i = 0; i < barrel.length; i++) {
if ((Man.bottom-10 >= barrel[i].top)&&(Man.bottom-10 <= barrel[i].bottom)&&(Man.Ladder == barrel[i].randomLadder)) {
print("GAME OVER!");
run = false;
}
if ((Man.top >= barrel[i].top)&&(Man.top <= barrel[i].bottom)&&(Man.Ladder == barrel[i].randomLadder)) {
print("GAME OVER!");
run = false;
}
}
}
if (run == true) {
background.createBackground();
Man.ladders();
Man.movement();
Man.createMan();
//spawns a barrel every second
if (millis()> time + 10) {
newBarrel = false;
print(" " + barrelTotal + " ");
time = time + 10;
barrelTotal = barrelTotal+1;
newBarrel = true;
}
for (int i = 0; i < barrelTotal; i++) {
if (newBarrel == true) {
}
barrel[i].gravity();
barrel[i].createBarrel();
}
//if(barrelTotal == 100){
//for (int i = 0; i < 50; i++){
// barrel[i] = "???";
//}
//}
}
}
Use an ArrayList instead of a native array. ArrayList will expand capacity as needed, whereas an array is fixed size and cannot be changed (you'd need to create a new larger array each time, which under the covers is what an ArrayList handles for you).
You can use ArrayList for this. You will change
// from
Barrel[] barrel = new Barrel[100]; // i suggest naming it to barrels instead of barrel
// to
ArrayList<Barrel> barrel = new ArrayList<>();
// or better
List<Barrel> barrel = new ArrayList<>();
// from
for (int i = 0; i < barrel.length; i++) {
barrel[i] = new Barrel();
}
// to
for (int i = 0; i < barrel.length; i++) {
barrel.add(new Barrel());
}
// from
barrel[i].<some-method()/attribute>
// to
barrel.get(i).<some-method()/attribute>
// etc
I highly recommend this for getting started with lists
https://docs.oracle.com/javase/tutorial/collections/interfaces/list.html
I am trying to utilize a .properties file to get a list of strings and transform them into an array to be added with javassist later in my program. However, I keep getting an arrayoutofboundsexception 0 with the following data in properties:
modify.spells.in.
void configure(Properties options)
{
String nameSpace;
ArrayList<String> spellList = new ArrayList<String>();
String[] tokens;
for(String key : options.stringPropertyNames()) {
if(key.startsWith("modify.spells.in.")) {
nameSpace = key.substring(17);
tokens = options.getProperty(key).split(",");
for(String token : tokens) {
if(spellList.contains(nameSpace + "." + token)) {
continue;
}
spellList.add(nameSpace + "." + token);
}
}
}
if(spellList.size() == 0) {
itemSpells = new String[]{
"Fire1", "Fire2", "Fire3", "Lit1", "Lit2", "Lit3", "Ice1", "Ice2",
"Ice3"
};
for(int i = 0; i < itemSpells.length; i++) {
itemSpells[i] = "com.ragdoll.spells." + itemSpells[i];
}
} else {
itemSpells = spellList.toArray(new String[0]);
}
The properties file string is as follows:
modify.spells.in.com.ragdoll.spells=Fire3,Lit3,Ice3
The expression to edit the existing code is as follows:
I have a HookManager to add in interceptSpells(itemSpells);
private void interceptSpells(String[] classes) throws NotFoundException, CannotCompileException
{
CtClass c;
ClassPool cp = HookManager.getInstance().getClassPool();
CtMethod m = null;
// CAST -
for(int i = 0; i < classes.length; i++) {
final int j = i;
c = cp.get(classes[i]);
m = c.getDeclaredMethods("doEffect")[0];
m.instrument(new ExprEditor() {
public void edit(MethodCall m) throws CannotCompileException {
if (m.getMethodName().equals("addSpellEffect")) {
logger.info("Intercepting (1) " + classes[j]);
m.replace(
"$_ = $proceed($$);"
+ "com.rev.spellmod.getInstance().addSpellEffectCaster($0, eff, performer); "
);
} else if(m.getMethodName().equals("improvePower")) {
logger.info("Intercepting (2) " + classes[j]);
m.replace(
"$_ = $proceed($$);"
+ "com.rev.spellmod.getInstance().replaceSpellEffectCaster($0, eff, performer); "
);
}
}
});
I feel as though I have declared the namespace and am splitting the list correctly. If I add just one spell in the .properties file, it works. As soon as I add more than one it points back to the intercept code with the arrayoutofboundsexception. If I leave it blank, it also works with the pre-determined spells, but I was hoping to be able to modify the spells on the go rather the recompiling each time.
Any thoughts or help would be appreciated!
I realized the doEffect was the issue. Some of the spells inherited doEffect from another class and so that was producing the ArrayOutOfBoundsException not the parsing of the string which was correct.
So i have checked through the previously posted prims algorithm posts. and i cant find one that satisfies my teachers requirements. I worked on this code with him, and have it mostly working. however for somereason when it gets to a certian point, it breaks and goes to the wrong edge.
'''public int prims(T startVertex) {
int tempWeight = 0;
int championWeight = 0;
int totalWeight = 0;
int i = 0;
boolean firstOne = false;
T championVertex = null;
T currentVertex = null;
T checkVertex = null;
T championMarked = null;
UnboundedQueueInterface<T> vertexQueue = new LinkedUnbndQueue<T>();
clearMarks();
markVertex(startVertex);
currentVertex = startVertex;
do {
for (int y = 0; y < numVertices; y++) {
currentVertex = vertices[y];
if (isMarked(currentVertex)) {
championWeight = 0;
championVertex = null;
checkVertex = null;
firstOne = true;
vertexQueue = getToVertices(currentVertex);
while (!vertexQueue.isEmpty()) {
checkVertex = vertexQueue.dequeue();
if ((!(isMarked(checkVertex)))) {
tempWeight = weightIs(currentVertex, checkVertex);
if (championWeight > tempWeight || firstOne == true) {
championWeight = tempWeight;
championVertex = checkVertex;
championMarked = currentVertex;
firstOne = false;
}
}
}
}
}
System.out.println((String) championMarked + (String) championVertex + championWeight);
markVertex(championVertex);
totalWeight += championWeight;
} while (!(getUnmarked() == null));
System.out.println("Total cost is " + totalWeight);
return totalWeight; '''
when i run it i get the following output
Graph 1
AD1
DF4
FC3
FE12
FZ17
Enull0
the output is correct for the graph until the line FE12. it should be CE4. when i run debug, i watch the code find the answer, but then jumps up to the for loop and looses the right answer. I know there is an error in my logic, but I cant quite figure it out. Your input is appreciated. thanks
So i have figured out my issue, I needed to put the resets for the code, after the code outputs the solution, otherwise where they were, if there were any vertices left to check that were not used already, the code would loose the current values.
they needed to go here
'''System.out.println((String) championMarked + (String) championVertex +
championWeight);
markVertex(championVertex);
totalWeight += championWeight;
championWeight = 0;
championVertex = null;
checkVertex = null;
firstOne = true;
} while (!(getUnmarked() == null));'''
I want to get probability score for the extracted names using NameFinderME, but using the provided model gives very bad probabilities using the probs function.
For example, "Scott F. Fitzgerald" gets a score around 0.5 (averaging log probabilities, and taking an exponent), while "North Japan" and "Executive Vice President, Corporate Relations and Chief Philanthropy Officer" both get a score higher than 0.9...
I have more than 2 million first names, and another 2 million last names (with their frequency counts) And I want to synthetically create a huge dataset from outer multiplication of the first names X middle names (using the first names pool) X last names.
The problem is, I don't even get to go over all the last names once (even when discarding freq counts and only using each name only once) before I get a GC overhead limit exceeded exception...
I'm implementing a ObjectStream and give it to the train function:
public class OpenNLPNameStream implements ObjectStream<NameSample> {
private List<Map<String, Object>> firstNames = null;
private List<Map<String, Object>> lastNames = null;
private int firstNameIdx = 0;
private int firstNameCountIdx = 0;
private int middleNameIdx = 0;
private int middleNameCountIdx = 0;
private int lastNameIdx = 0;
private int lastNameCountIdx = 0;
private int firstNameMaxCount = 0;
private int middleNameMaxCount = 0;
private int lastNameMaxCount = 0;
private int firstNameKBSize = 0;
private int lastNameKBSize = 0;
Span span[] = new Span[1];
String fullName[] = new String[3];
String partialName[] = new String[2];
private void increaseFirstNameCountIdx()
{
firstNameCountIdx++;
if (firstNameCountIdx == firstNameMaxCount) {
firstNameIdx++;
if (firstNameIdx == firstNameKBSize)
return; //no need to update anything - this is the end of the run...
firstNameMaxCount = getFirstNameMaxCount(firstNameIdx);
firstNameCountIdx = 0;
}
}
private void increaseMiddleNameCountIdx()
{
lastNameCountIdx++;
if (middleNameCountIdx == middleNameMaxCount) {
if (middleNameIdx == firstNameKBSize) {
resetMiddleNameIdx();
increaseFirstNameCountIdx();
} else {
middleNameMaxCount = getMiddleNameMaxCount(middleNameIdx);
middleNameCountIdx = 0;
}
}
}
private void increaseLastNameCountIdx()
{
lastNameCountIdx++;
if (lastNameCountIdx == lastNameMaxCount) {
lastNameIdx++;
if (lastNameIdx == lastNameKBSize) {
resetLastNameIdx();
increaseMiddleNameCountIdx();
}
else {
lastNameMaxCount = getLastNameMaxCount(lastNameIdx);
lastNameCountIdx = 0;
}
}
}
private void resetLastNameIdx()
{
lastNameIdx = 0;
lastNameMaxCount = getLastNameMaxCount(0);
lastNameCountIdx = 0;
}
private void resetMiddleNameIdx()
{
middleNameIdx = 0;
middleNameMaxCount = getMiddleNameMaxCount(0);
middleNameCountIdx = 0;
}
private int getFirstNameMaxCount(int i)
{
return 1; //compromised on using just
//String occurences = (String) firstNames.get(i).get("occurences");
//return Integer.parseInt(occurences);
}
private int getMiddleNameMaxCount(int i)
{
return 3; //compromised on using just
//String occurences = (String) firstNames.get(i).get("occurences");
//return Integer.parseInt(occurences);
}
private int getLastNameMaxCount(int i)
{
return 1;
//String occurences = (String) lastNames.get(i).get("occurences");
//return Integer.parseInt(occurences);
}
#Override
public NameSample read() throws IOException {
if (firstNames == null) {
firstNames = CSVFileTools.readFileFromInputStream("namep_first_name_idf.csv", new ClassPathResource("namep_first_name_idf.csv").getInputStream());
firstNameKBSize = firstNames.size();
firstNameMaxCount = getFirstNameMaxCount(0);
middleNameMaxCount = getFirstNameMaxCount(0);
}
if (lastNames == null) {
lastNames = CSVFileTools.readFileFromInputStream("namep_last_name_idf.csv",new ClassPathResource("namep_last_name_idf.csv").getInputStream());
lastNameKBSize = lastNames.size();
lastNameMaxCount = getLastNameMaxCount(0);
}
increaseLastNameCountIdx();;
if (firstNameIdx == firstNameKBSize)
return null; //we've finished iterating over all permutations!
String [] sentence;
if (firstNameCountIdx < firstNameMaxCount / 3)
{
span[0] = new Span(0,2,"Name");
sentence = partialName;
sentence[0] = (String)firstNames.get(firstNameIdx).get("first_name");
sentence[1] = (String)lastNames.get(lastNameIdx).get("last_name");
}
else
{
span[0] = new Span(0,3,"name");
sentence = fullName;
sentence[0] = (String)firstNames.get(firstNameIdx).get("first_name");
sentence[2] = (String)lastNames.get(lastNameIdx).get("last_name");
if (firstNameCountIdx < 2*firstNameCountIdx/3) {
sentence[1] = (String)firstNames.get(middleNameIdx).get("first_name");
}
else {
sentence[1] = ((String)firstNames.get(middleNameIdx).get("first_name")).substring(0,1) + ".";
}
}
return new NameSample(sentence,span,true);
}
#Override
public void reset() throws IOException, UnsupportedOperationException {
firstNameIdx = 0;
firstNameCountIdx = 0;
middleNameIdx = 0;
middleNameCountIdx = 0;
lastNameIdx = 0;
lastNameCountIdx = 0;
firstNameMaxCount = 0;
middleNameMaxCount = 0;
lastNameMaxCount = 0;
}
#Override
public void close() throws IOException {
reset();
firstNames = null;
lastNames = null;
}
}
And
TokenNameFinderModel model = NameFinderME.train("en","person",new OpenNLPNameStream(),TrainingParameters.defaultParams(),new TokenNameFinderFactory());
model.serialize(new FileOutputStream("trainedNames.bin",false));
I get the following error after a few minutes of running:
java.lang.OutOfMemoryError: GC overhead limit exceeded
at opennlp.tools.util.featuregen.WindowFeatureGenerator.createFeatures(WindowFeatureGenerator.java:112)
at opennlp.tools.util.featuregen.AggregatedFeatureGenerator.createFeatures(AggregatedFeatureGenerator.java:79)
at opennlp.tools.util.featuregen.CachedFeatureGenerator.createFeatures(CachedFeatureGenerator.java:69)
at opennlp.tools.namefind.DefaultNameContextGenerator.getContext(DefaultNameContextGenerator.java:118)
at opennlp.tools.namefind.DefaultNameContextGenerator.getContext(DefaultNameContextGenerator.java:37)
at opennlp.tools.namefind.NameFinderEventStream.generateEvents(NameFinderEventStream.java:113)
at opennlp.tools.namefind.NameFinderEventStream.createEvents(NameFinderEventStream.java:137)
at opennlp.tools.namefind.NameFinderEventStream.createEvents(NameFinderEventStream.java:36)
at opennlp.tools.util.AbstractEventStream.read(AbstractEventStream.java:62)
at opennlp.tools.util.AbstractEventStream.read(AbstractEventStream.java:27)
at opennlp.tools.util.AbstractObjectStream.read(AbstractObjectStream.java:32)
at opennlp.tools.ml.model.HashSumEventStream.read(HashSumEventStream.java:46)
at opennlp.tools.ml.model.HashSumEventStream.read(HashSumEventStream.java:29)
at opennlp.tools.ml.model.TwoPassDataIndexer.computeEventCounts(TwoPassDataIndexer.java:130)
at opennlp.tools.ml.model.TwoPassDataIndexer.<init>(TwoPassDataIndexer.java:83)
at opennlp.tools.ml.AbstractEventTrainer.getDataIndexer(AbstractEventTrainer.java:74)
at opennlp.tools.ml.AbstractEventTrainer.train(AbstractEventTrainer.java:91)
at opennlp.tools.namefind.NameFinderME.train(NameFinderME.java:337)
Edit: After increasing the memory of the JVM to 8GB, I still don't get past the first 2 million last names, but now the Exception is:
java.lang.OutOfMemoryError: Java heap space
at java.util.HashMap.resize(HashMap.java:703)
at java.util.HashMap.putVal(HashMap.java:662)
at java.util.HashMap.put(HashMap.java:611)
at opennlp.tools.ml.model.AbstractDataIndexer.update(AbstractDataIndexer.java:141)
at opennlp.tools.ml.model.TwoPassDataIndexer.computeEventCounts(TwoPassDataIndexer.java:134)
at opennlp.tools.ml.model.TwoPassDataIndexer.<init>(TwoPassDataIndexer.java:83)
at opennlp.tools.ml.AbstractEventTrainer.getDataIndexer(AbstractEventTrainer.java:74)
at opennlp.tools.ml.AbstractEventTrainer.train(AbstractEventTrainer.java:91)
at opennlp.tools.namefind.NameFinderME.train(NameFinderME.java:337)
It seems the problem stems from the fact I'm creating a new NameSample along with new Spans and Strings at every read call... But I can't reuse Spans or NameSamples, since they're immutables.
Should I just write my own language model, is there a better Java library for doing this sort of thing (I'm only interested in getting the probability the extracted text is actually a name) are there parameters I should tweak for the model I'm training?
Any advice would be appreciated.
So, here is my functions:
private void sendLeft() {
leftSendersIndexes = newLeftSendersIndexes;
Agent rightRecepient;
int rightRecepientIdx = 0;
Agent leftSender;
for (int i = 0; i < leftSendersIndexes.size(); i++) {
rightRecepientIdx = leftSendersIndexes.get(i) + 1;
rightRecepient = list.get(rightRecepientIdx);
leftSender = list.get(rightRecepientIdx - 1);
rightRecepient.setNewLeftMsg(leftSender.getLeftMsg());
rightRecepient.setLeftMsg(0); // reset left messages
}
}
private void sendRight() {
rightSendersIndexes = newRightSendersIndexes;
Agent leftRecepient;
int leftRecepientIdx = 0;
Agent rightSender;
for (int i = 0; i < rightSendersIndexes.size(); i++) {
leftRecepientIdx = rightSendersIndexes.get(i) - 1;
leftRecepient = list.get(leftRecepientIdx);
rightSender = list.get(leftRecepientIdx + 1);
leftRecepient.setNewRightMsg(rightSender.getRightMsg());
}
}
They are very similar. The problem is that in first function I have leftRecepientIdx+1 and after that leftRecepientIdx-1 and I have leftRecepientIdx-1 and leftRecepientIdx+1 in second function. I may to combine two functions in one and add a boolean parameter. But is there a better way to get rid of duplication?
One way to do that is with this refactoring:
private void sendLeft() {
leftSendersIndexes = newLeftSendersIndexes;
send(leftSendersIndexes, -1);
}
private void sendRight() {
rightSendersIndexes = newRightSendersIndexes;
send(rightSendersIndexes, +1);
}
private void send(List<Integer> indexes, int direction) {
for (int i = 0; i < indexes.size(); i++) {
int recipientIdx = indexes.get(i) - direction;
Agent recipient = list.get(recipientIdx);
Agent sender = list.get(recipientIdx + direction);
if (direction == -1) {
recipient.setNewLeftMsg(sender.getLeftMsg());
recipient.setLeftMsg(0); // reset left messages
}
else {
recipient.setNewRightMsg(sender.getRightMsg());
}
}
}
The send method encapsulates the logic based on the direction parameter: +1 for right, -1 for left.
The order in which those appears is important, I would suggest merging, but, I have no idea what that would do. Keep them separate, if this was borrowed, this was made on purpose.
Both functions are some send functions where sender and receiver are different and reset may happen. So I would try to make one function with arguments sender, receiver and boolean reset.