I'm trying to add a new book item, that can be enchanted just like normal books, but that have a higher enchantability. Everything works so far, just one thing is missing: When you enchant normal books, they get converted to Enchanted Books. The code that does that, is located in the onButtonClick method of the EnchantmentScreenHandler class:
public boolean onButtonClick(PlayerEntity player, int id) {
if (id >= 0 && id < this.enchantmentPower.length) {
//...
if (//...) {
return false;
} else if (//...) {
return false;
} else {
this.context.run((world, pos) -> {
//...
if (//...) {
player.applyEnchantmentCosts(itemStack, i);
boolean bl = itemStack.isOf(Items.BOOK); //<--- "bl" is the important variable
if (bl) {
itemStack3 = new ItemStack(Items.ENCHANTED_BOOK);
NbtCompound nbtCompound = itemStack.getNbt();
if (nbtCompound != null) {
itemStack3.setNbt(nbtCompound.copy());
}
this.inventory.setStack(0, itemStack3);
}
}
So if the item that gets enchanted, is a Book, it gets later replaced with an Enchanted Book. So my idea was to just modify the assigment of bl using the #ModifyVariable annotation and then check, if the item is made of my modded book. But whatever I try, I can't get it to work. I always get the error No refMap loaded.. I figured it's not working, because the variable bl is located inside a lambda function, but I'm not sure if that's really the issue. Of course I can just replace the entire body of the method, but that wouldn't be good for compatibility with other mods.
Related
I am trying to solve a puzzle, and it has been suggested that I use backtracking - I did not know the term so did some investigation, and found the following in Wikipedia:
In order to apply backtracking to a specific class of problems, one must provide the data P for the particular instance of the problem that is to be solved, and six procedural parameters, root, reject, accept, first, next, and output. These procedures should take the instance data P as a parameter and should do the following:
root(P): return the partial candidate at the root of the search tree.
reject(P,c): return true only if the partial candidate c is not worth completing.
accept(P,c): return true if c is a solution of P, and false otherwise.
first(P,c): generate the first extension of candidate c.
next(P,s): generate the next alternative extension of a candidate, after the extension s.
output(P,c): use the solution c of P, as appropriate to the application.
The backtracking algorithm reduces the problem to the call backtrack(root(P)), where backtrack is the following recursive procedure:
procedure backtrack(c) is
if reject(P, c) then return
if accept(P, c) then output(P, c)
s ← first(P, c)
while s ≠ NULL do
backtrack(s)
s ← next(P, s)
I have attempted to use this method for my solution, but after the method finds a rejected candidate it just starts again and finds the same route, rather than the next possible one.
I now don't think I have used the next(P,s) correctly, because I don't really understand the wording 'after the extension s'.
I've tried 2 methods:
(a) in the first() function, generating all possible extensions, storing them in a list, then using the first. The next() function then uses the other extensions from the list in turn. But this maybe can't work because of the calls to backtrack() in between the calls to next().
(b) adding a counter to the data (i.e. the class that includes all the grid info) and incrementing this for each call of next(). But can't work out where to reset this counter to zero.
Here's the relevant bit of code for method (a):
private PotentialSolution tryFirstTrack(PotentialSolution ps)
{
possibleTracks = new List<PotentialSolution>();
for (Track trytrack = Track.Empty + 1; trytrack < Track.MaxVal; trytrack++)
{
if (validMove(ps.nextSide, trytrack))
{
ps.SetCell(trytrack);
possibleTracks.Add(ps);
}
}
return tryNextTrack(ps);
}
private PotentialSolution tryNextTrack(PotentialSolution ps)
{
if (possibleTracks.Count == 0)
{
ps.SetCell(Track.Empty);
return null;
}
ps = possibleTracks.First();
// don't use same one again
possibleTracks.Remove(ps);
return ps;
}
private bool backtrackTracks(PotentialSolution ps)
{
if (canExit)
{
return true;
}
if (checkOccupiedCells(ps))
{
ps = tryFirstTrack(ps);
while (ps != null)
{
// 'testCells' is a copy of the grid for use with graphics - no need to include graphics in the backtrack stack
testCells[ps.h, ps.w].DrawTrack(g, ps.GetCell());
if (ps.TestForExit(endColumn, ref canExit) != Track.MaxVal)
{
drawRowColTotals(ps);
return true;
}
ps.nextSide = findNextSide(ps.nextSide, ps.GetCell(), ref ps.h, ref ps.w);
if (ps.h >= 0 && ps.h < cellsPerSide && ps.w >= 0 && ps.w < cellsPerSide)
{
backtrackTracks(ps);
ps = tryNextTrack(ps);
}
else
return false;
}
return false;
}
return false;
}
and here's some code using random choices. This works fine, so I conclude that the methods checkOccupiedCells() and findNextSide() are working correctly.
private bool backtrackTracks(PotentialSolution ps)
{
if (canExit)
{
return true;
}
if (checkOccupiedCells(ps))
{
Track track = createRandomTrack(ps);
if (canExit)
return true;
if (track == Track.MaxVal)
return false;
ps.SetCell(track);
ps.nextSide = findNextSide(ps.nextSide, track, ref ps.h, ref ps.w);
if (ps.h >= 0 && ps.h < cellsPerSide && ps.w >= 0 && ps.w < cellsPerSide)
backtrackTracks(ps);
else
return false;
}
}
If it helps, there's more background info in the puzzle itself here
I am new to RxJava2.
I am trying to get a list of Transaction object both from cache and from server.
I want to compare the server value to cache value and if the server value is the same, then ignore it.
I was able to do it easily using .scan() because we can return null and when null is returned from the .scan() the value got ignored(filtered).
RxJava 1
private Observable<List<Transaction>> getTransactionsFromCacheAndServer() {
return Observable.concat(
getTransactionsFromCache(),
getTransactionsFromServer()
)
.scan((p1, p2) -> {
if (p1 == null && p2 != null) {
return p2;
} else if (p1 != null && !isListSame(p1, p2)) {
return p2;
} else {
return null;
}
});
}
With RxJava 2, since I cannot return null anymore, things are not easy.
RxJava 2
private Observable<List<Transaction>> getTransactionsFromCacheAndServer() {
return Observable.concat(
getTransactionsFromCache(),
getTransactionsFromServer()
)
.map(FilterObject::new)
.scan((filterObject1, filterObject2) -> {
List<Transaction> p1 = (List<Transaction>)filterObject1.value;
List<Transaction> p2 = (List<Transaction>)filterObject2.value;
if (p1.size() == 0 && p2.size() > 0) {
return filterObject2;
} else if (!isListSame(p1, p2)) {
return filterObject2;
} else {
filterObject2.filter = true;
return filterObject2;
}
})
.filter(filterObject -> !filterObject.filter)
.map(filterObject -> (List<Transaction>)filterObject.value);
}
Where FilterObject is:
public class FilterObject {
public Object value;
public boolean filter;
public FilterObject(Object value) {
this.value = value;
}
}
Even though I can achieve the same thing using above method, it seems very ugly. Also I had to include two maps which might not be so performance friendly.
Is there a simple/clean way to achieve what I want?
I don't think there is a generic solution to this problem, since an empty list and a list that needs to be filtered (which happens to be empty in all cases) are two different things (the output of the scan) and needs to be handled differently.
However, in your particular case you never emit an empty list, except maybe for the first output.
(I am using String instead Transaction, shouldn't matter)
private Observable<List<String>> getTransactionsFromCacheAndServer() {
return Observable.concat(
getTransactionsFromCache(),
getTransactionsFromServer()
)
.filter(list -> !list.isEmpty())
// If you prefer a consistent empty list over the first
// empty list emission getting filtered
.startWith((List<String>) Collections.EMPTY_LIST)
// Newly emitted value cannot be empty, it only depends only on the comparison
.distinctUntilChanged(this::isListSame);
}
That's the closest I could get with as few operators as possible. Hope it solves your problem.
Based on andras' answer, I modified little bit to achieve what I want.
private Observable<List<String>> getTransactionsFromCacheAndServer() {
return Observable.concat(
getTransactionsFromCache(),
getTransactionsFromServer()
)
.filter(list -> !list.isEmpty())
.distinctUntilChanged(this::isListSame)
.switchIfEmpty(Observable.just(new ArrayList<>()));
}
Andreas' answer will always receive an empty list and then a real data.
My solution above will receive:
1. Data from cache (and then data from server if different)
2. Empty list if both cache and server returns Empty list.
//I wrote java code for insertion method on doubly linked list but there is a infinite loop //when I run it. I'm trying to find a bug, but have not found so far. any suggestions?
//it is calling a helper function
public IntList insertionSort ( ) {
DListNode soFar = null;
for (DListNode p=myHead; p!=null; p=p.myNext) {
soFar = insert (p, soFar);
}
return new IntList (soFar);
}
// values will be in decreasing order.
private DListNode insert (DListNode p, DListNode head) {
DListNode q=new DListNode(p.myItem);
if(head==null){
head=q;
return head;
}
if(q.myItem>=head.myItem){
DListNode te=head;
q.myNext=te;
te.myPrev=q;
q=head;
return head;
}
DListNode a;
boolean found=false;
for(a=head; a!=null;){
if(a.myItem<q.myItem){
found=true;
break;
}
else{
a=a.myNext;
}
}
if(found==false){
DListNode temp=myTail;
temp.myNext=q;
q.myPrev=temp;
myTail=q;
return head;
}
if(found==true){
DListNode t;
t=a.myPrev;
a.myPrev=q;
t.myNext=q;
q.myPrev=t;
q.myNext=a;
}
return head;
}
Your code is a bit hard to read through but I noticed a few problems
First:
handling the case where you are inserting a number at the head of the list:
if(q.myItem>=head.myItem){
DListNode te=head;
q.myNext=te;
te.myPrev=q;
q=head;
return head;
}
specifically the line q=head; and the return. q=head can be removed, and it should return q not head because q is the new head. I think what you meant to do was head=q; return head;. The current code will essentially add the new node on the front but never return the updated head so they will "fall off the edge" in a way.
Second:
I am assuming myTail is some node reference you are keeping like myHead to the original list. I don't think you want to be using it like you are for the sorted list you are constructing. When you loop through looking for the place to insert in the new list, use that to determine the tail reference and use that instead.
DListNode lastCompared = null;
for(a=head; a!=null; a=a.myNext) {
lastCompared = a;
if(a.myItem<q.myItem) {
break;
}
}
if( a )
{
// insert node before a
...
}
else
{
// smallest value yet, throw on the end
lastCompared.myNext = q;
q.myPrev = lastCompared;
return head;
}
Finally make sure myPrev and myNext are being properly initialized to null in the constructor for DListNode.
disclaimer I didn't get a chance to test the code I added here, but hopefully it at least gets you thinking about the solution.
A couple stylistic notes (just a sidenote):
the repeated if->return format is not the cleanest in my opinion.
I generally try and limit the exit points in functions
There are a lot of intermediate variables being used and the names are super
ambiguous. At the very least try and use some more descriptive
variable names.
comments are always a good idea. Just make sure they don't just explain what the code is doing - instead try and
convey thought process and what is trying to be accomplished.
I'm writing a tinyMce plugin which contains a section of code, replacing one element for another. I'm using the editor's dom instance to create the node I want to insert, and I'm using the same instance to do the replacement.
My code is as follows:
var nodeData =
{
"data-widgetId": data.widget.widgetKey(),
"data-instanceKey": "instance1",
src: "/content/images/icon48/cog.png",
class: "widgetPlaceholder",
title: data.widget.getInfo().name
};
var nodeToInsert = ed.dom.create("img", nodeData);
// Insert this content into the editor window
if (data.mode == 'add') {
tinymce.DOM.add(ed.getBody(), nodeToInsert);
}
else if (data.mode == 'edit' && data.selected != null) {
var instanceKey = $(data.selected).attr("data-instancekey");
var elementToReplace = tinymce.DOM.select("[data-instancekey=" + instanceKey + "]");
if (elementToReplace.length === 1) {
ed.dom.replace(elementToReplace[0], nodeToInsert);
}
else {
throw new "No element to replace with that instance key";
}
}
TinyMCE breaks during the replace, here:
replace : function(n, o, k) {
var t = this;
if (is(o, 'array'))
n = n.cloneNode(true);
return t.run(o, function(o) {
if (k) {
each(tinymce.grep(o.childNodes), function(c) {
n.appendChild(c);
});
}
return o.parentNode.replaceChild(n, o);
});
},
..with the error Cannot call method 'replaceChild' of null.
I've verified that the two argument's being passed into replace() are not null and that their parentNode fields are instantiated. I've also taken care to make sure that the elements are being created and replace using the same document instance (I understand I.E has an issue with this).
I've done all this development in Google Chrome, but I receive the same errors in Firefox 4 and IE8 also. Has anyone else come across this?
Thanks in advance
As it turns out, I was simply passing in the arguments in the wrong order. I should have been passing the node I wanted to insert first, and the node I wanted to replace second.
Like the title says, I'm trying to find out if I need to include a script library that my ASP.net UserControl needs to work. I don't want to include it multiple times per page, but I want my control to be able to be used multiple times on the same page.
How can I, in the codebehind of my control, check to see if a given <script/> tag is present?
This is .Net 2.0, no LINQ.
If !Page.ClientScript.IsClientScriptIncludeRegistered("jQuery")
Page.ClientScript.RegisterClientScriptInclude("jQuery", "/scripts/jquery.js");
or if you need a script block, And want to include the control's type:
if (!Page.ClientScript.IsClientScriptBlockRegistered(this.GetType(), "myScript"))
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "myScript"
, "<script>alert('xx');</script>", false);
This might be a bit overkill for your usage, but I'm using it to search for existing CSS and JS before adding to the page:
private static bool HeaderLinkExists(Page page, string path)
{
path = path.ToLowerInvariant();
foreach (Control c in page.Header.Controls)
{
if (c is HtmlLink)
{
// stylesheet (or other links), check href
HtmlLink link = (HtmlLink)c;
if (link.Href.ToLowerInvariant().Contains(path))
{
return true;
}
}
else if (c is HtmlGenericControl)
{
// any generic html tag, check for src or href
HtmlGenericControl hgc = (HtmlGenericControl)c;
if ((!string.IsNullOrEmpty(hgc.Attributes["src"]) && hgc.Attributes["src"].ToLowerInvariant().Contains(path)) || (!string.IsNullOrEmpty(hgc.Attributes["href"]) && hgc.Attributes["href"].ToLowerInvariant().Contains(path)))
{
return true;
}
}
else if (c is LiteralControl)
{
// scripts or other html literal controls, use regex to look for src or hrefs and check each one
LiteralControl lit = (LiteralControl)c;
if (MatchLiteralText(lit.Text, path))
{
return true;
}
}
else if (c is Literal)
{
// similar to above, use regex to look for src or hrefs and check each one
Literal lit = (Literal)c;
if (MatchLiteralText(lit.Text, path))
{
return true;
}
}
}
return false;
}
private static readonly Regex linkMatcher = new Regex(#"(?:src|href)\s*=\s*([""']?)(?<LinkValue>[^\1]+?)[\1>]", RegexOptions.Compiled);
private static bool MatchLiteralText(string text, string path)
{
if (!string.IsNullOrEmpty(text))
{
text = text.ToLowerInvariant()
foreach (Match m in linkMatcher.Matches(text))
{
if (m.Groups["LinkValue"].Value.Contains(path))
{
return true;
}
}
}
return false;
}
// usage:
if (!HeaderLinkExists(page, "/css/controlstyles.css"))
{
HtmlHeadUtility.RegisterStylesheetInHeader(page, "~/css/controlstyles.css");
}
if (!HeaderLinkExists(page, "/js/controlscript.js"))
{
HtmlHeadUtility.RegisterClientScriptIncludeInHeader(page, "~/js/controlscript.js");
}
It works great if you're sure that the LINK or SCRIPT is guaranteed to be in the HEAD.
No, there isn't.
Instead, you should maintain a set of <script> tags that have already been included, and update it whenever you add a script. (For example, a [ThreadStatic] static List<String>)
I would suggest re-thinking your problem/solution. It seems like what you are trying to do would couple your user control and the pages that use it. This would require that a page reference that script in order to use a control.
Is there any reason you can't just put the script tag in your user control so that the pages consuming your user control don't need to know that they need to include a specific script tag to work?
I tend to think that if you want to just use a control you should be able to just use it.