Skip to content

major rewrite to pattern buffers#4910

Open
GilbertzRivi wants to merge 2 commits into
GregTechCEu:1.20.1from
GilbertzRivi:pattern-buffer-remake
Open

major rewrite to pattern buffers#4910
GilbertzRivi wants to merge 2 commits into
GregTechCEu:1.20.1from
GilbertzRivi:pattern-buffer-remake

Conversation

@GilbertzRivi
Copy link
Copy Markdown

What

Remake of pattern buffers to improve performance

Implementation Details

The base greg buffers have 27 pattern slots, each is acting like a distinct input bus for a multiblock, so its basically like slapping 27 distinct dual hatches on the multiblock and it has to scan them all for recipes. So i made it so each buffer has only 1 distinct bus, for all its patterns, but it has blocking mode with allow the same pattern to be pushed and there is additional bus for each proxy. So 1 buffer + 3 proxy is 4 distinct busses for the multi to scan for recipes. It also allows to make bigger buffers for mod developers without them being unusable due to lag. From what i understand it should work roughly the same because a multi will do only 1 type of a recipe at once anyway. But because there is another bus for each proxy, 4 machines can make 4 recipes, all machines also see all busses so if only 1 pattern is used at the time all machines can do it in parallel and each can use max parallels because blocking allows the same pattern to be pushed. It also does one additional check before running the recipe handler, it checks if any item or fluid the slot has currently in its inventory matches any from the recipe and only if it does it runs the recipe handler. It also short circuits when the slot is just empty. The blocking mode with allow the same works like that each pattern pushed is held in a list and only pattern that is the same as the one in the list is allowed to be pushed to the slot, and it also will push the same pattern to the same slot always. I also added caching on some things that get queried more than once per tick.

AI Usage

  • Yes AI driven tools were used for this pull request.

Agent Used

ClaudeCode Sonet 4.6

Agent Usage Description

I used it to dig into the code so I can get a wider view of the repo easier. It was also used in very early stages of developing to make some base and boiler plate I can work with. The whole system, what it does and how it works, i came up with myself in 100%.

Outcome

Heavily optimizes pattern buffers.

How Was This Tested

It is a part of my addon that I added to my instance of monifactory. I use it heavily and they are not lagging my server almost at all. For comparsion when I first unlocked pattern buffers, i made one and used it on my ABS tower, my TPS fell down to 3 after I connected it to ME system instantly. Now I moved the code from my addon here and tested on dev instance with a few RHFs and LCRs, and they work as expected.

Additional Information

The comparsion chart bellow shows base buffers vs expanded from gtmutils vs insane buffers, where the insane are the ones I made with my custom logic. The optimization mentioned is done in another PR here
image

Potential Compatibility Issues

If the buffer has anything inside its slots, after this update it will lost those runtime items.

@GilbertzRivi GilbertzRivi requested a review from a team as a code owner June 5, 2026 07:15
@github-actions github-actions Bot added the 1.20.1 label Jun 5, 2026
Copy link
Copy Markdown
Contributor

@screret screret left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please don't use var for 'simple' types (e.g. ones without nested generics); it makes code harder to read in the github review UI.

@Getter
@SaveField
protected final InternalSlot[] internalInventory = new InternalSlot[MAX_PATTERN_COUNT];
protected final InternalSlot[] workerSlotStorage = new InternalSlot[MAX_PATTERN_COUNT];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renaming this field will delete all patterns that are currently stored in the buffer, so you'll need to add some backwards compatibility code for this.
TagCompatibilityFixer.java and its uses have examples you could reference for that.

private final List<WorkerItemHandler> workerItemHandlers = new ArrayList<>();
private final List<WorkerFluidHandler> workerFluidHandlers = new ArrayList<>();
private final List<RecipeHandlerList> workerHandlerLists = new ArrayList<>();
private @Nullable List<RecipeHandlerList> workerHandlersView;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Collections.unmodifiableList always mirrors the source list so this should be sufficient:

Suggested change
private @Nullable List<RecipeHandlerList> workerHandlersView;
private final @UnmodifiableView List<RecipeHandlerList> workerHandlersView = Collections.unmodifiableList(workerHandlerLists);

Also apply the other suggestions in this class so this works :)

});

workerHandlerLists.add(new WorkerRHL(itemH, fluidH));
workerHandlersView = null;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the unmodifiable list

Suggested change
workerHandlersView = null;

workerItemHandlers.remove(last);
workerFluidHandlers.remove(last);
workerHandlerLists.remove(last);
workerHandlersView = null;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the unmodifiable list

Suggested change
workerHandlersView = null;

Comment on lines +403 to +405
if (workerHandlersView == null)
workerHandlersView = Collections.unmodifiableList(workerHandlerLists);
return workerHandlersView;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (workerHandlersView == null)
workerHandlersView = Collections.unmodifiableList(workerHandlerLists);
return workerHandlersView;
return workerHandlersView;

}

@Override
public List<RecipeHandlerList> getRecipeHandlers() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public List<RecipeHandlerList> getRecipeHandlers() {
public @UnmodifiableView List<RecipeHandlerList> getRecipeHandlers() {

var slot = workerSlots.get(i);
boolean empty = slot.isItemEmpty() && slot.isFluidEmpty();
if (empty) workerPatterns.set(i, null);
var cur = workerPatterns.get(i);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename this variable to something more descriptive, like currentPattern

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants