The next step is offering the drain and source menu interactions from the pump in Library_Tank. I see the pump as a "tank", too, but it immediately transfers the stored liquid with its timer function.
Then the tests fail and give some errors for me. Otherwise it looks good, I'd suggest to move all liquid related libraries into the folder Libraries.ocd/LiquidControl.ocd.
Maybe rename SetLiquidName to SetLiquidType. Also seeing the pump as an "immediate" tank might lead to problems, are you sure this is the right way.
What I'd like to see at the end is: oil field->pipe->pump->pipe->steamengine =>power.
As a solution I always color the line from the steam engine red. However, what about connecting pumps in line (this would be stupid though, because with the current situation they all need power)? Or other connections between containers and pumps. Maybe we should have the first part of the line be red, then green where it reaches the other object, and vice versa?
Or what do you want to achieve? I imagine a use-case where the pump pumps oil into the steam engine.


PS: And I'd find it weird if pumps actually contained liquid


So if you wanted to avoid the storage, you would have to do an extra check before pumping, which makes the script more complicated.
Also, I think it's not totally unrealistic for the pump to store a few pixels of liquid internally as being "in the pump".
The branch has the following stuff:
- you can connect pipes to the pump and/or steam engine
- there is oil
- the pump delivers oil to the steam engine, which burns it
- the steam engine can also be fueled with oil barrels
- tests for the connection logic and liquid container interface are in Tests.ocf\LiquidContainer.ocs, added two more tests in PowerSystem.ocs
Could someone please test the changes in actual gameplay? Furthermore, oil does not yet burn.

>Is force push supported in the repository?
What? Why would you want to do that.
Some fast remarks:
* Don't comment out lines just replace them.
* The last test in the power system is an infinite loop, so your tests should go before.
* Remove the flagpole in test 21.
* SetProperty("Value", 10); -> this.Value = 10;
* Script warning (needs to be failsafe):
[21:55:39] WARNING: Translate: no translation for string "MaterialLava"
[21:55:39] by: Object(31)->UpdateLiquidContainer() (/home/maikel/openclonk/repos/build/planet/Objects.ocd/Items.ocd/Tools.ocd/Barrel.ocd/Script.c:121)
[21:55:39] by: Object(31)->ChangeLiquidFillLevel(100) (/home/maikel/openclonk/repos/build/planet/Objects.ocd/Libraries.ocd/LiquidContainer.ocd/Script.c:99)
[21:55:39] by: Object(31)->SetLiquidFillLevel(100) (/home/maikel/openclonk/repos/build/planet/Objects.ocd/Libraries.ocd/LiquidContainer.ocd/Script.c:86)
[21:55:39] by: Object(31)->SetLiquidContainer("Lava",100) (/home/maikel/openclonk/repos/build/planet/Objects.ocd/Libraries.ocd/LiquidContainer.ocd/Script.c:190)
[21:55:39] by: Global->Test8_Execute() (/home/maikel/openclonk/repos/planet/Tests.ocf/LiquidContainer.ocs/Script.c:410)
[21:55:39] by: FxIntTestControlTimer(0,{Name = "IntTestControl", launched = false, plr = 0, result = 1, testnr = 8}) (/home/maikel/openclonk/repos/planet/Tests.ocf/LiquidContainer.ocs/Script.c:115)
* We need an intuitive interface where you can see how much liquid is held in a tank.
* What is the difference between the tank and liquid container library?
* What kind of other unit tests do you have in mind?
Otherwise it looks very good and promising so far (at least the power tests).
* The commented lines have been removed in a later commit
* I did not know about the infinite loop. Why do you want to design it that way? I thought the test has one purpose: proove that you can get a working power network with a pump that generates energy by pumping downward, one that consumes energy by pumping upward, and a third source that provides the power difference. I tried to make the test such that it is not an infinite loop, but still tests that aspect.
* The SetProperty-stuff is some kind of relic from the barrel. The whole value calculation there is seriously broken in my opinion, but it does not matter because the barrel cannot be sold anyway.
* Difference between tank and container: The container can be anything that can hold liquids, such as a barrel, bottle. The tank is a structure that can hold liquids (as such it inherits from the liquid container), but it also allows to connect pipes to it, by using the pipe or in the interaction menu.
* As for the interface: Do you mean some kind of GUI component?
* Other unit tests: No idea yet. Maybe have the pump transfer liquids with different pipe connections, but that is already handled in the liquid container unit test (probably not all of the combinations though).

> * The warnings in the unit test probably cannot be avoided, maybe by overloading the barrel for the test or not translating the string if the barrel does not support the liquid: I fill lava into it, it is looking for the string "MaterialLava" in its StringTblXX.txt, but obviously it cannot find that, because the barrel cannot carry lava. How else can I test a liquid that the barrel is not supposed to hold?
For example, you can just make them locals:
local BarrelNames = {
Lava = "$LavaBarrel$",
Water = "$WaterBarrel$",
};
and then, in a function:
func GetNameForBarrel(string material)
{
var name = BarrelNames[material]; // Name known?
if (!name) name = "$FilledBarrel$" // Otherwise, return a standard name
return name;
}
Of course we could also add a failsafe-parameter for translate. But I don't like that too much, because it makes code paths dependent on the loaded language pack.
>* I did not know about the infinite loop. Why do you want to design it that way? I thought the test has one purpose: proove that you can get a working power network with a pump that generates energy by pumping downward, one that consumes energy by pumping upward, and a third source that provides the power difference. I tried to make the test such that it is not an infinite loop, but still tests that aspect.
That is okay for now, I'll change stuff afterwards if I want something different.
>* As for the interface: Do you mean some kind of GUI component?
Yes, how do I know how many oil my steam engine hold, and how many it can hold.
[22:02:11] ERROR: '->': no function "GetBarrelMaterial" in object "Object(5136)".
[22:02:11] by: Object(5136)->CanBeStackedWith(Object(5128)) (/home/maikel/openclonk/repos/build/planet/Objects.ocd/Items.ocd/Tools.ocd/Barrel.ocd/Script.c:205)
[22:02:11] by: Object(5146)->FxIntRefreshContentsMenuTimer(Object(5146),{Name = "IntRefreshContentsMenu", last_inventory = [], menu_index = 0, obj = Object(5160), slot = 0},1) (/home/maikel/openclonk/repos/build/planet/Objects.ocd/HUD.ocd/ObjectInteractionMenu.ocd/Script.c:1004)

This will not work as construction material, though. My suggestions from there on:
- make liquid object save the contained volume
- make liquid object enter liquid containers only
- make steam engine a liquid container for the "fuel" liquid/material that already exists, instead of an oil container, and have it convert oil to fuel at a 1:1 ratio
- modify behavior of steam engine so that liquids are pumped into it as long as the fuel count is below a certain value, so the pump works as long as the steam engine is burning fuel
? modify barrels so that they have an extra inventory slot (where the liquid object will be displayed)
? make liquid objects C4D_Object instead of C4D_StaticBack and have an actual graphics, not just a picture
? make liquid objects convert to respective material if they are not contained in a liquid container, or particles in case of non-material liquids (fuel)

I am really still playing with the idea of a "water" object that would just be contained in the objects :x

Also I think it should be a property instead of a callback (because it's called on a timer and it would also be consistent with ApertureOffset), but I have no strong opinion about this.
* We have a new structure, the tank, which can contain liquids of a certain type and only that type.
* The pumps source is in some liquid and the drain connected to the tank, the pump fills the tank.
So now when the tank is full the pump stops working presumably. Questions:
* Can I connect multiple tanks to one pump? How do we determine which one will be filled.
* Can I connect multiple tanks to each other (enhancing the total capacity)? [My opinion: don't allow this]
* What happens if the pump tries to pump the wrong material?
* Can I do Pump->Tank->Pump->Steam Engine, or Pump->Tank->Steam Engine (arrows indicate liquid flow)?
You see there are lots of design issues to resolve if we complicate matters. For now though I propose to add a Tank structure with place holder graphics to which the pump directly connects. This can then be filled and can store barrels which can be filled.
Edit: Sorry for being so negative/precise/obnoxious here, but I know from the power system that we should be really careful about the design and test thoroughly before adding it to master. I appreciate the effort you put in here!
The pump can have source and drain, but not neutral; the steam engine can only have neutral (a connected drain from the pump counts as neutral in this case).
So, in the current implementation:
>* Can I connect multiple tanks to one pump? How do we determine which one will be filled.
No.
>* Can I connect multiple tanks to each other (enhancing the total capacity)? [My opinion: don't allow this]
No.
>* What happens if the pump tries to pump the wrong material?
Its the same as if the pump were clogged.
>* Can I do Pump->Tank->Pump->Steam Engine, or Pump->Tank->Steam Engine (arrows indicate liquid flow)?
If you designed a tank object that can have an input and output pipe, then you could have the first version, but not the second (since the tank does not know how to transfer liquid to another object, and the steam engine does not know how to request liquid from another object. Only the pump can transfer stuff.

> * We have a new structure, the tank, which can contain liquids of a certain type and only that type.
Would that magically be able to compress all liquids? Because otherwise I don't see a difference between a liquid tank and just using an area in the landscape that you have prepared with wall kits, etc. Also, it would have to be a huge structure!
Or would it be for oil only, the idea being that it provides protection from enemy firestones?

>Also, it would have to be a huge structure!
It would obviously be huge towards the back of the screen.
I'll take a few days off from doing this, to get a clear view on it.
This has advantages and drawbacks though:
+ liquid objects are one object, similar to a "stackable" object
+ the barrel does not need an implementation for emptying, it just ejects the liquid object which then sprays its contents
+ the steam engine can contain "fuel" now, displays the amount of fuel as contained liquid object "fuel"
- the code of the liquid container is not as intuitive anymore, because it has to contain code for handling a liquid object, instead of handling liquid type and volume: The liquid object contains that information, and the container has to save that object and delegates calls to that object. However, the logic for creating new objects and partially transferring liquid from one liquid object to the container is convoluted, even though I tried to keep it as straight forward as possible
- the producer library does not benefit from the liquid objects: a liquid container can have only one type of liquid, so you have several options: a) allow several liquids in a producer (one could limit this, but why would you put 100x water and 50x lava in a bakery for example. This is the same as putting water or lava barrels into it), b) allow one type of liquid per producer only (which seriously limits producers that produce objects that rely on multiple liquids, such as oil and/or water)
- the producer library does not benefit from the liquid objects: only the steam engine can have a pipe connection at the moment.
- the producer library does not benefit from the liquid objects: it has to distinguish between liquid containers ("IsLiquidContainer" - barrels, can partially remove liquid from it), "real" liquid objects ("IsLiquid" - water, liquid can be partially removed), and "pseudo" liquid objects ("IsLiquid" - ice, does not really contain liquid and gets removed entirely)
Would be nice to get some feedback on this. The latest version is available on my fork, branch "liquid_container"

>liquid objects are one object, similar to a "stackable" object
Yes, they should use the stackable-interface then.
>a liquid container can have only one type of liquid, so you have several options
At the moment, producers can take only the objects they need for production (you can't put loam into a chemical lab). I guess that would be the same there? (And wouldn't need any changes?)
> the producer library does not benefit from the liquid objects: it has to distinguish between liquid containers ("IsLiquidContainer" - barrels, can partially remove liquid from it), "real" liquid objects ("IsLiquid" - water, liquid can be partially removed), and "pseudo" liquid objects ("IsLiquid" - ice, does not really contain liquid and gets removed entirely)
Why does the producer library need new code? It just contains the liquids, right? So it should work if they are just IsStackable objects. And if the producer does not work with IsStackable right now, it should be made to work - because we have many exceptions everywhere for the stackable stuff anyway.
Using the stackable interface for liquids should reduce the required code quite a bit. Or did I misunderstand anything?
>Yes, they should use the stackable-interface then.
That's what they did, but it prooved to be not that useful: Objects that include Library_Stackable can be stack up to 999 objects. For liquids that is not enough, because one barrel contains 300 items already, and I do not want to have 3x999xWater in a container. Having another "non-limited, but not infinite" mode for stackable objects seemed to be strange, too.
>At the moment, producers can take only the objects they need for production (you can't put loam into a chemical lab). I guess that would be the same there? (And wouldn't need any changes?)
Lets say the chemical lab needs water for one product, and oil for another product. You can put oil into it, but then you would not be able to put any water into it (as a reserve) until the oil is used up. Once could make an exception, so that producers can contain any amount of liquids at the same time, but that would effectively make all producers a liquid storage that can hold e.g. 100+ barrels worth of water each. On the other hand, one could actually put 100+ barrels inside the producer at the moment, so no actual change.
>Or did I misunderstand anything?
There are three kinds object objects for liquid at the moment:
* Liquid containers (Barrel), marked by "IsLiquidContainer". These contain liquid and should not be removed by the producer, just emptied.
* Liquid objects (Liquid_Water), has a function "IsLiquid" that returns water. These also "contain/are" liquid, and should not be removed by the producer, just emptied. I.e. if there is 90 water in the producer and it needs 60, then 30 should remain.
* Other objects (Ice) that also have a function "IsLiquid", but the producer just counts how many water is contained in such an item and removes the entire object.
So in the end I need to distinguish these items, or make them use the same interface. This is somewhat hindered by the fact that the producer handles fuel and liquid completely different from normal components. If that were not the case, then the code might become less convoluted indeed.
Still the actual questions that we must ask are these:
- what is the benefit of having, say 100 water items in the kitchen, instead of a barrel that contains 100 water?
- would barrel empty into the kitchen if you transfer a water barrel to the kitchen, leaving the empty barrel in the Clonk?
- if not, then why include the water item? It would only ever enter the kitchen if there were a pipe attached to it, which is not possible at the moment.
Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill